From bc4b2e7b77fe557880aaf1c66b7aae8a57d6ce5e Mon Sep 17 00:00:00 2001 From: Matthew Beale Date: Tue, 9 Nov 2021 17:15:28 -0500 Subject: [PATCH] Add vendored PR of Ember, add to CI --- .github/workflows/main.yml | 9 +- config/ember-try.js | 14 +- .../dependencies/@glimmer/destroyable.js | 203 + .../dependencies/@glimmer/encoder.js | 46 + .../dependencies/@glimmer/env.js | 4 + .../dependencies/@glimmer/global-context.js | 183 + .../dependencies/@glimmer/low-level.js | 77 + .../dependencies/@glimmer/manager.js | 906 + .../dependencies/@glimmer/node.js | 173 + .../dependencies/@glimmer/opcode-compiler.js | 3141 + .../dependencies/@glimmer/owner.js | 21 + .../dependencies/@glimmer/program.js | 519 + .../dependencies/@glimmer/reference.js | 440 + .../dependencies/@glimmer/runtime.js | 7290 ++ .../dependencies/@glimmer/util.js | 598 + .../dependencies/@glimmer/validator.js | 768 + .../dependencies/@glimmer/vm.js | 48 + .../dependencies/@glimmer/wire-format.js | 52 + .../dependencies/@simple-dom/document.js | 365 + .../dependencies/backburner.js | 973 + .../dependencies/dag-map.js | 209 + .../dependencies/route-recognizer.js | 685 + .../dependencies/router_js.js | 1963 + ember-vendored-pr-19806/dependencies/rsvp.js | 2452 + .../ember-template-compiler.js | 21896 ++++ .../ember-template-compiler.map | 1 + ember-vendored-pr-19806/ember-testing.js | 2134 + ember-vendored-pr-19806/ember-testing.map | 1 + ember-vendored-pr-19806/ember.debug.js | 61482 +++++++++++ ember-vendored-pr-19806/ember.debug.map | 1 + ember-vendored-pr-19806/header/license.js | 9 + ember-vendored-pr-19806/header/loader.js | 97 + .../@ember/-internals/bootstrap/index.js | 10 + .../-internals/browser-environment/index.js | 12 + .../@ember/-internals/container/index.js | 948 + .../@ember/-internals/environment/index.js | 253 + .../@ember/-internals/error-handling/index.js | 23 + .../-internals/extension-support/index.js | 2 + .../lib/container_debug_adapter.js | 105 + .../extension-support/lib/data_adapter.js | 575 + .../@ember/-internals/glimmer/index.js | 6512 ++ .../packages/@ember/-internals/meta/index.js | 1 + .../@ember/-internals/meta/lib/meta.js | 595 + .../packages/@ember/-internals/metal/index.js | 3647 + .../@ember/-internals/overrides/index.js | 1 + .../packages/@ember/-internals/owner/index.js | 65 + .../@ember/-internals/routing/index.js | 17 + .../-internals/routing/lib/ext/controller.js | 212 + .../-internals/routing/lib/location/api.js | 103 + .../routing/lib/location/auto_location.js | 244 + .../routing/lib/location/hash_location.js | 170 + .../routing/lib/location/history_location.js | 290 + .../routing/lib/location/none_location.js | 124 + .../-internals/routing/lib/location/util.js | 97 + .../-internals/routing/lib/services/router.js | 534 + .../routing/lib/services/routing.js | 120 + .../-internals/routing/lib/system/cache.js | 42 + .../routing/lib/system/controller_for.js | 14 + .../-internals/routing/lib/system/dsl.js | 217 + .../-internals/routing/lib/system/engines.js | 1 + .../routing/lib/system/generate_controller.js | 52 + .../routing/lib/system/query_params.js | 7 + .../routing/lib/system/route-info.js | 225 + .../-internals/routing/lib/system/route.js | 1948 + .../-internals/routing/lib/system/router.js | 1622 + .../routing/lib/system/router_state.js | 27 + .../routing/lib/system/transition.js | 195 + .../@ember/-internals/routing/lib/utils.js | 261 + .../@ember/-internals/runtime/.gitignore | 1 + .../packages/@ember/-internals/runtime/README | 12 + .../@ember/-internals/runtime/index.js | 22 + .../@ember/-internals/runtime/lib/compare.js | 152 + .../@ember/-internals/runtime/lib/ext/rsvp.js | 59 + .../@ember/-internals/runtime/lib/is-equal.js | 61 + .../-internals/runtime/lib/mixins/-proxy.js | 104 + .../runtime/lib/mixins/action_handler.js | 186 + .../-internals/runtime/lib/mixins/array.js | 1758 + .../runtime/lib/mixins/comparable.js | 34 + .../runtime/lib/mixins/container_proxy.js | 130 + .../runtime/lib/mixins/enumerable.js | 16 + .../-internals/runtime/lib/mixins/evented.js | 135 + .../runtime/lib/mixins/mutable_enumerable.js | 18 + .../runtime/lib/mixins/observable.js | 409 + .../runtime/lib/mixins/promise_proxy.js | 207 + .../runtime/lib/mixins/registry_proxy.js | 216 + .../lib/mixins/target_action_support.js | 151 + .../runtime/lib/system/array_proxy.js | 335 + .../runtime/lib/system/core_object.js | 914 + .../runtime/lib/system/namespace.js | 64 + .../-internals/runtime/lib/system/object.js | 55 + .../runtime/lib/system/object_proxy.js | 81 + .../@ember/-internals/runtime/lib/type-of.js | 112 + .../packages/@ember/-internals/utils/index.js | 828 + .../packages/@ember/-internals/views/index.js | 11 + .../-internals/views/lib/compat/attrs.js | 2 + .../lib/compat/fallback-view-registry.js | 2 + .../-internals/views/lib/component_lookup.js | 13 + .../views/lib/mixins/action_support.js | 37 + .../views/lib/mixins/child_views_support.js | 28 + .../views/lib/mixins/class_names_support.js | 83 + .../views/lib/mixins/view_state_support.js | 20 + .../views/lib/mixins/view_support.js | 365 + .../views/lib/system/action_manager.js | 13 + .../views/lib/system/event_dispatcher.js | 314 + .../-internals/views/lib/system/utils.js | 204 + .../-internals/views/lib/views/core_view.js | 76 + .../-internals/views/lib/views/states.js | 27 + .../views/lib/views/states/default.js | 18 + .../views/lib/views/states/destroying.js | 13 + .../views/lib/views/states/has_element.js | 30 + .../views/lib/views/states/in_dom.js | 33 + .../views/lib/views/states/pre_render.js | 3 + .../packages/@ember/application/index.js | 3 + .../packages/@ember/application/instance.js | 451 + .../@ember/application/lib/application.js | 965 + .../@ember/application/lib/lazy_load.js | 69 + .../packages/@ember/application/namespace.js | 1 + .../packages/@ember/array/index.js | 2 + .../packages/@ember/array/mutable.js | 1 + .../packages/@ember/array/proxy.js | 1 + .../packages/@ember/canary-features/index.js | 79 + .../packages/@ember/component/helper.js | 1 + .../packages/@ember/component/index.js | 3 + .../@ember/component/template-only.js | 32 + .../packages/@ember/controller/index.js | 61 + .../@ember/controller/lib/controller_mixin.js | 52 + .../@ember/debug/container-debug-adapter.js | 1 + .../packages/@ember/debug/data-adapter.js | 1 + .../packages/@ember/debug/index.js | 278 + .../@ember/debug/lib/capture-render-tree.js | 23 + .../packages/@ember/debug/lib/deprecate.js | 176 + .../packages/@ember/debug/lib/handlers.js | 30 + .../packages/@ember/debug/lib/testing.js | 7 + .../packages/@ember/debug/lib/warn.js | 92 + .../@ember/deprecated-features/index.js | 4 + .../packages/@ember/destroyable/index.js | 238 + .../packages/@ember/engine/index.js | 430 + .../packages/@ember/engine/instance.js | 177 + .../@ember/engine/lib/engine-parent.js | 31 + .../packages/@ember/enumerable/index.js | 1 + .../packages/@ember/error/index.js | 14 + .../packages/@ember/helper/index.js | 315 + .../packages/@ember/instrumentation/index.js | 270 + .../packages/@ember/modifier/index.js | 3 + .../packages/@ember/object/compat.js | 44 + .../packages/@ember/object/computed.js | 3 + .../packages/@ember/object/core.js | 1 + .../packages/@ember/object/evented.js | 2 + .../packages/@ember/object/events.js | 1 + .../packages/@ember/object/index.js | 174 + .../packages/@ember/object/internals.js | 2 + .../object/lib/computed/computed_macros.js | 779 + .../lib/computed/reduce_computed_macros.js | 1059 + .../packages/@ember/object/mixin.js | 1 + .../packages/@ember/object/observable.js | 1 + .../packages/@ember/object/observers.js | 1 + .../@ember/object/promise-proxy-mixin.js | 1 + .../packages/@ember/object/proxy.js | 1 + .../packages/@ember/polyfills/index.js | 2 + .../packages/@ember/polyfills/lib/assign.js | 35 + .../packages/@ember/routing/auto-location.js | 1 + .../packages/@ember/routing/hash-location.js | 1 + .../@ember/routing/history-location.js | 1 + .../packages/@ember/routing/index.js | 1 + .../packages/@ember/routing/location.js | 1 + .../packages/@ember/routing/none-location.js | 1 + .../packages/@ember/routing/route.js | 1 + .../packages/@ember/routing/router.js | 1 + .../packages/@ember/runloop/index.js | 728 + .../packages/@ember/service/index.js | 84 + .../packages/@ember/string/index.js | 229 + .../@ember/string/lib/string_registry.js | 13 + .../@ember/template-compilation/index.js | 9 + .../packages/@ember/template-factory/index.js | 1 + .../packages/@ember/template/index.js | 1 + .../packages/@ember/test/adapter.js | 2 + .../packages/@ember/test/index.js | 28 + .../packages/@ember/utils/index.js | 2 + .../packages/@ember/version/index.js | 1 + .../packages/@glimmer/tracking/index.js | 203 + .../@glimmer/tracking/primitives/cache.js | 1 + .../packages/ember-babel.js | 195 + .../packages/ember-testing/index.js | 10 + .../ember-testing/lib/adapters/adapter.js | 54 + .../ember-testing/lib/adapters/qunit.js | 52 + .../ember-testing/lib/ext/application.js | 176 + .../packages/ember-testing/lib/ext/rsvp.js | 18 + .../packages/ember-testing/lib/helpers.js | 16 + .../ember-testing/lib/helpers/and_then.js | 3 + .../ember-testing/lib/helpers/current_path.js | 28 + .../lib/helpers/current_route_name.js | 27 + .../ember-testing/lib/helpers/current_url.js | 28 + .../ember-testing/lib/helpers/pause_test.js | 63 + .../ember-testing/lib/helpers/visit.js | 42 + .../ember-testing/lib/helpers/wait.js | 72 + .../ember-testing/lib/initializers.js | 16 + .../ember-testing/lib/setup_for_testing.js | 26 + .../packages/ember-testing/lib/test.js | 66 + .../ember-testing/lib/test/adapter.js | 29 + .../ember-testing/lib/test/helpers.js | 129 + .../lib/test/on_inject_helpers.js | 37 + .../lib/test/pending_requests.js | 20 + .../ember-testing/lib/test/promise.js | 72 + .../packages/ember-testing/lib/test/run.js | 8 + .../ember-testing/lib/test/waiters.js | 127 + .../packages/ember/index.js | 514 + .../packages/ember/version.js | 1 + .../tests/ember-testing.js | 2134 + .../tests/ember-testing.map | 1 + ember-vendored-pr-19806/tests/ember-tests.js | 84208 ++++++++++++++++ ember-vendored-pr-19806/tests/ember-tests.map | 1 + ember-vendored-pr-19806/tests/ember.js | 61482 +++++++++++ ember-vendored-pr-19806/tests/ember.map | 1 + ember-vendored-pr-19806/tests/index.html | 174 + ember-vendored-pr-19806/tests/loader.js | 97 + ember-vendored-pr-19806/tests/polyfill.js | 2154 + ember-vendored-pr-19806/tests/qunit/qunit.css | 478 + ember-vendored-pr-19806/tests/qunit/qunit.js | 6527 ++ ember-vendored-pr-19806/tests/testem.js | 3 + 219 files changed, 299681 insertions(+), 20 deletions(-) create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/destroyable.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/encoder.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/env.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/global-context.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/low-level.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/manager.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/node.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/opcode-compiler.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/owner.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/program.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/reference.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/runtime.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/util.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/validator.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/vm.js create mode 100644 ember-vendored-pr-19806/dependencies/@glimmer/wire-format.js create mode 100644 ember-vendored-pr-19806/dependencies/@simple-dom/document.js create mode 100644 ember-vendored-pr-19806/dependencies/backburner.js create mode 100644 ember-vendored-pr-19806/dependencies/dag-map.js create mode 100644 ember-vendored-pr-19806/dependencies/route-recognizer.js create mode 100644 ember-vendored-pr-19806/dependencies/router_js.js create mode 100644 ember-vendored-pr-19806/dependencies/rsvp.js create mode 100644 ember-vendored-pr-19806/ember-template-compiler.js create mode 100644 ember-vendored-pr-19806/ember-template-compiler.map create mode 100644 ember-vendored-pr-19806/ember-testing.js create mode 100644 ember-vendored-pr-19806/ember-testing.map create mode 100644 ember-vendored-pr-19806/ember.debug.js create mode 100644 ember-vendored-pr-19806/ember.debug.map create mode 100644 ember-vendored-pr-19806/header/license.js create mode 100644 ember-vendored-pr-19806/header/loader.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/bootstrap/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/browser-environment/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/container/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/environment/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/error-handling/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/extension-support/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/extension-support/lib/data_adapter.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/glimmer/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/meta/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/meta/lib/meta.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/metal/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/overrides/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/owner/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/ext/controller.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/api.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/auto_location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/hash_location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/history_location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/none_location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/location/util.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/services/router.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/services/routing.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/cache.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/controller_for.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/dsl.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/engines.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/generate_controller.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/query_params.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/route-info.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/route.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/router.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/router_state.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/system/transition.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/routing/lib/utils.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/.gitignore create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/README create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/compare.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/ext/rsvp.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/is-equal.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/-proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/action_handler.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/array.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/comparable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/enumerable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/evented.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/mutable_enumerable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/observable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/promise_proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/system/array_proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/system/core_object.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/system/namespace.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/system/object.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/system/object_proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/runtime/lib/type-of.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/utils/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/compat/attrs.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/compat/fallback-view-registry.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/component_lookup.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/mixins/action_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/mixins/child_views_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/mixins/class_names_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/mixins/view_state_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/mixins/view_support.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/system/action_manager.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/system/event_dispatcher.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/system/utils.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/core_view.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states/default.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states/destroying.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states/has_element.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states/in_dom.js create mode 100644 ember-vendored-pr-19806/packages/@ember/-internals/views/lib/views/states/pre_render.js create mode 100644 ember-vendored-pr-19806/packages/@ember/application/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/application/instance.js create mode 100644 ember-vendored-pr-19806/packages/@ember/application/lib/application.js create mode 100644 ember-vendored-pr-19806/packages/@ember/application/lib/lazy_load.js create mode 100644 ember-vendored-pr-19806/packages/@ember/application/namespace.js create mode 100644 ember-vendored-pr-19806/packages/@ember/array/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/array/mutable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/array/proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/canary-features/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/component/helper.js create mode 100644 ember-vendored-pr-19806/packages/@ember/component/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/component/template-only.js create mode 100644 ember-vendored-pr-19806/packages/@ember/controller/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/controller/lib/controller_mixin.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/container-debug-adapter.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/data-adapter.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/lib/capture-render-tree.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/lib/deprecate.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/lib/handlers.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/lib/testing.js create mode 100644 ember-vendored-pr-19806/packages/@ember/debug/lib/warn.js create mode 100644 ember-vendored-pr-19806/packages/@ember/deprecated-features/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/destroyable/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/engine/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/engine/instance.js create mode 100644 ember-vendored-pr-19806/packages/@ember/engine/lib/engine-parent.js create mode 100644 ember-vendored-pr-19806/packages/@ember/enumerable/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/error/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/helper/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/instrumentation/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/modifier/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/compat.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/computed.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/core.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/evented.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/events.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/internals.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/lib/computed/computed_macros.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/lib/computed/reduce_computed_macros.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/mixin.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/observable.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/observers.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/promise-proxy-mixin.js create mode 100644 ember-vendored-pr-19806/packages/@ember/object/proxy.js create mode 100644 ember-vendored-pr-19806/packages/@ember/polyfills/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/polyfills/lib/assign.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/auto-location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/hash-location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/history-location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/none-location.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/route.js create mode 100644 ember-vendored-pr-19806/packages/@ember/routing/router.js create mode 100644 ember-vendored-pr-19806/packages/@ember/runloop/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/service/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/string/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/string/lib/string_registry.js create mode 100644 ember-vendored-pr-19806/packages/@ember/template-compilation/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/template-factory/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/template/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/test/adapter.js create mode 100644 ember-vendored-pr-19806/packages/@ember/test/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/utils/index.js create mode 100644 ember-vendored-pr-19806/packages/@ember/version/index.js create mode 100644 ember-vendored-pr-19806/packages/@glimmer/tracking/index.js create mode 100644 ember-vendored-pr-19806/packages/@glimmer/tracking/primitives/cache.js create mode 100644 ember-vendored-pr-19806/packages/ember-babel.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/index.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/adapters/adapter.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/adapters/qunit.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/ext/application.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/ext/rsvp.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/and_then.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/current_path.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/current_route_name.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/current_url.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/pause_test.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/visit.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/helpers/wait.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/initializers.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/setup_for_testing.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/adapter.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/helpers.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/on_inject_helpers.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/pending_requests.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/promise.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/run.js create mode 100644 ember-vendored-pr-19806/packages/ember-testing/lib/test/waiters.js create mode 100644 ember-vendored-pr-19806/packages/ember/index.js create mode 100644 ember-vendored-pr-19806/packages/ember/version.js create mode 100644 ember-vendored-pr-19806/tests/ember-testing.js create mode 100644 ember-vendored-pr-19806/tests/ember-testing.map create mode 100644 ember-vendored-pr-19806/tests/ember-tests.js create mode 100644 ember-vendored-pr-19806/tests/ember-tests.map create mode 100644 ember-vendored-pr-19806/tests/ember.js create mode 100644 ember-vendored-pr-19806/tests/ember.map create mode 100644 ember-vendored-pr-19806/tests/index.html create mode 100644 ember-vendored-pr-19806/tests/loader.js create mode 100644 ember-vendored-pr-19806/tests/polyfill.js create mode 100644 ember-vendored-pr-19806/tests/qunit/qunit.css create mode 100644 ember-vendored-pr-19806/tests/qunit/qunit.js create mode 100644 ember-vendored-pr-19806/tests/testem.js diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6f1a630..27f812b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,14 +42,7 @@ jobs: strategy: matrix: - ember-version: - [ - ember-lts-3.20, - ember-lts-3.24, - ember-lts-3.28, - ember-beta, - ember-release, - ] + ember-version: [ember-vendored-pr-19806, ember-lts-3.28] steps: - name: Checkout diff --git a/config/ember-try.js b/config/ember-try.js index de737ca..8e2163c 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -8,18 +8,10 @@ module.exports = async function () { useYarn: true, scenarios: [ { - name: 'ember-lts-3.20', + name: 'ember-vendored-pr-19806', npm: { devDependencies: { - 'ember-source': '~3.20.5', - }, - }, - }, - { - name: 'ember-lts-3.24', - npm: { - devDependencies: { - 'ember-source': '~3.24.3', + 'ember-source': 'file:./ember-vendored-pr-19806', }, }, }, @@ -55,8 +47,6 @@ module.exports = async function () { }, }, }, - embroiderSafe(), - embroiderOptimized(), ], }; }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/destroyable.js b/ember-vendored-pr-19806/dependencies/@glimmer/destroyable.js new file mode 100644 index 0000000..34c44aa --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/destroyable.js @@ -0,0 +1,203 @@ +import { DEBUG } from '@glimmer/env'; +import { debugToString } from '@glimmer/util'; +import { scheduleDestroy, scheduleDestroyed } from '@glimmer/global-context'; + +let DESTROYABLE_META = new WeakMap(); + +function push(collection, newItem) { + if (collection === null) { + return newItem; + } else if (Array.isArray(collection)) { + collection.push(newItem); + return collection; + } else { + return [collection, newItem]; + } +} + +function iterate(collection, fn) { + if (Array.isArray(collection)) { + for (let i = 0; i < collection.length; i++) { + fn(collection[i]); + } + } else if (collection !== null) { + fn(collection); + } +} + +function remove(collection, item, message) { + if (DEBUG) { + let collectionIsItem = collection === item; + let collectionContainsItem = Array.isArray(collection) && collection.indexOf(item) !== -1; + + if (!collectionIsItem && !collectionContainsItem) { + throw new Error(String(message)); + } + } + + if (Array.isArray(collection) && collection.length > 1) { + let index = collection.indexOf(item); + collection.splice(index, 1); + return collection; + } else { + return null; + } +} + +function getDestroyableMeta(destroyable) { + let meta = DESTROYABLE_META.get(destroyable); + + if (meta === undefined) { + meta = { + parents: null, + children: null, + eagerDestructors: null, + destructors: null, + state: 0 + /* Live */ + + }; + + if (DEBUG) { + meta.source = destroyable; + } + + DESTROYABLE_META.set(destroyable, meta); + } + + return meta; +} + +function associateDestroyableChild(parent, child) { + if (DEBUG && isDestroying(parent)) { + throw new Error('Attempted to associate a destroyable child with an object that is already destroying or destroyed'); + } + + let parentMeta = getDestroyableMeta(parent); + let childMeta = getDestroyableMeta(child); + parentMeta.children = push(parentMeta.children, child); + childMeta.parents = push(childMeta.parents, parent); + return child; +} +function registerDestructor(destroyable, destructor, eager = false) { + if (DEBUG && isDestroying(destroyable)) { + throw new Error('Attempted to register a destructor with an object that is already destroying or destroyed'); + } + + let meta = getDestroyableMeta(destroyable); + let destructorsKey = eager === true ? 'eagerDestructors' : 'destructors'; + meta[destructorsKey] = push(meta[destructorsKey], destructor); + return destructor; +} +function unregisterDestructor(destroyable, destructor, eager = false) { + if (DEBUG && isDestroying(destroyable)) { + throw new Error('Attempted to unregister a destructor with an object that is already destroying or destroyed'); + } + + let meta = getDestroyableMeta(destroyable); + let destructorsKey = eager === true ? 'eagerDestructors' : 'destructors'; + meta[destructorsKey] = remove(meta[destructorsKey], destructor, DEBUG && 'attempted to remove a destructor that was not registered with the destroyable'); +} //////////// + +function destroy(destroyable) { + let meta = getDestroyableMeta(destroyable); + if (meta.state >= 1 + /* Destroying */ + ) return; + let { + parents, + children, + eagerDestructors, + destructors + } = meta; + meta.state = 1 + /* Destroying */ + ; + iterate(children, destroy); + iterate(eagerDestructors, destructor => destructor(destroyable)); + iterate(destructors, destructor => scheduleDestroy(destroyable, destructor)); + scheduleDestroyed(() => { + iterate(parents, parent => removeChildFromParent(destroyable, parent)); + meta.state = 2 + /* Destroyed */ + ; + }); +} + +function removeChildFromParent(child, parent) { + let parentMeta = getDestroyableMeta(parent); + + if (parentMeta.state === 0 + /* Live */ + ) { + parentMeta.children = remove(parentMeta.children, child, DEBUG && "attempted to remove child from parent, but the parent's children did not contain the child. This is likely a bug with destructors."); + } +} + +function destroyChildren(destroyable) { + let { + children + } = getDestroyableMeta(destroyable); + iterate(children, destroy); +} +function _hasDestroyableChildren(destroyable) { + let meta = DESTROYABLE_META.get(destroyable); + return meta === undefined ? false : meta.children !== null; +} +function isDestroying(destroyable) { + let meta = DESTROYABLE_META.get(destroyable); + return meta === undefined ? false : meta.state >= 1 + /* Destroying */ + ; +} +function isDestroyed(destroyable) { + let meta = DESTROYABLE_META.get(destroyable); + return meta === undefined ? false : meta.state >= 2 + /* Destroyed */ + ; +} //////////// + +let enableDestroyableTracking; +let assertDestroyablesDestroyed; + +if (DEBUG) { + let isTesting = false; + + enableDestroyableTracking = () => { + if (isTesting) { + // Reset destroyable meta just in case, before throwing the error + DESTROYABLE_META = new WeakMap(); + throw new Error('Attempted to start destroyable testing, but you did not end the previous destroyable test. Did you forget to call `assertDestroyablesDestroyed()`'); + } + + isTesting = true; + DESTROYABLE_META = new Map(); + }; + + assertDestroyablesDestroyed = () => { + if (!isTesting) { + throw new Error('Attempted to assert destroyables destroyed, but you did not start a destroyable test. Did you forget to call `enableDestroyableTracking()`'); + } + + isTesting = false; + let map = DESTROYABLE_META; + DESTROYABLE_META = new WeakMap(); + let undestroyed = []; + map.forEach(meta => { + if (meta.state !== 2 + /* Destroyed */ + ) { + undestroyed.push(meta.source); + } + }); + + if (undestroyed.length > 0) { + let objectsToString = undestroyed.map(debugToString).join('\n '); + let error = new Error(`Some destroyables were not destroyed during this test:\n ${objectsToString}`); + error.destroyables = undestroyed; + throw error; + } + }; +} + +export { associateDestroyableChild, registerDestructor, unregisterDestructor, destroy, destroyChildren, _hasDestroyableChildren, isDestroying, isDestroyed, enableDestroyableTracking, assertDestroyablesDestroyed }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/encoder.js b/ember-vendored-pr-19806/dependencies/@glimmer/encoder.js new file mode 100644 index 0000000..781b8c7 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/encoder.js @@ -0,0 +1,46 @@ +import { DEBUG } from '@glimmer/env'; + +class InstructionEncoderImpl { + constructor(buffer) { + this.buffer = buffer; + this.size = 0; + } + + encode(type, machine) { + if (type > 255 + /* TYPE_SIZE */ + ) { + throw new Error(`Opcode type over 8-bits. Got ${type}.`); + } + + let first = type | machine | arguments.length - 2 << 8 + /* ARG_SHIFT */ + ; + this.buffer.push(first); + + for (let i = 2; i < arguments.length; i++) { + let op = arguments[i]; + + if (DEBUG && typeof op === 'number' && op > 2147483647 + /* MAX_SIZE */ + ) { + throw new Error(`Operand over 32-bits. Got ${op}.`); + } + + this.buffer.push(op); + } + + this.size = this.buffer.length; + } + + patch(position, target) { + if (this.buffer[position + 1] === -1) { + this.buffer[position + 1] = target; + } else { + throw new Error('Trying to patch operand in populated slot instead of a reserved slot.'); + } + } + +} + +export { InstructionEncoderImpl }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/env.js b/ember-vendored-pr-19806/dependencies/@glimmer/env.js new file mode 100644 index 0000000..5e4b238 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/env.js @@ -0,0 +1,4 @@ +const DEBUG = false; +const CI = false; + +export { DEBUG, CI }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/global-context.js b/ember-vendored-pr-19806/dependencies/@glimmer/global-context.js new file mode 100644 index 0000000..37098f0 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/global-context.js @@ -0,0 +1,183 @@ +import { DEBUG } from '@glimmer/env'; + +/** + * This package contains global context functions for Glimmer. These functions + * are set by the embedding environment and must be set before initial render. + * + * These functions should meet the following criteria: + * + * - Must be provided by the embedder, due to having framework specific + * behaviors (e.g. interop with classic Ember behaviors that should not be + * upstreamed) or to being out of scope for the VM (e.g. scheduling a + * revalidation) + * - Never differ between render roots + * - Never change over time + * + */ + +/** + * Schedules a VM revalidation. + * + * Note: this has a default value so that tags can warm themselves when first loaded. + */ + +let scheduleRevalidate = () => {}; +/** + * Schedules a destructor to run + * + * @param destroyable The destroyable being destroyed + * @param destructor The destructor being scheduled + */ + +let scheduleDestroy; +/** + * Finalizes destruction + * + * @param finalizer finalizer function + */ + +let scheduleDestroyed; +/** + * Hook to provide iterators for `{{each}}` loops + * + * @param value The value to create an iterator for + */ + +let toIterator; +/** + * Hook to specify truthiness within Glimmer templates + * + * @param value The value to convert to a boolean + */ + +let toBool; +/** + * Hook for specifying how Glimmer should access properties in cases where it + * needs to. For instance, accessing an object's values in templates. + * + * @param obj The object provided to get a value from + * @param path The path to get the value from + */ + +let getProp; +/** + * Hook for specifying how Glimmer should update props in cases where it needs + * to. For instance, when updating a template reference (e.g. 2-way-binding) + * + * @param obj The object provided to get a value from + * @param prop The prop to set the value at + * @param value The value to set the value to + */ + +let setProp; +/** + * Hook for specifying how Glimmer should access paths in cases where it needs + * to. For instance, the `key` value of `{{each}}` loops. + * + * @param obj The object provided to get a value from + * @param path The path to get the value from + */ + +let getPath; +/** + * Hook for specifying how Glimmer should update paths in cases where it needs + * to. For instance, when updating a template reference (e.g. 2-way-binding) + * + * @param obj The object provided to get a value from + * @param path The path to get the value from + */ + +let setPath; +/** + * Hook to warn if a style binding string or value was not marked as trusted + * (e.g. HTMLSafe) + */ + +let warnIfStyleNotTrusted; +/** + * Hook to customize assertion messages in the VM. Usages can be stripped out + * by using the @glimmer/vm-babel-plugins package. + */ + +let assert; +/** + * Hook to customize deprecation messages in the VM. Usages can be stripped out + * by using the @glimmer/vm-babel-plugins package. + */ + +let deprecate; +let globalContextWasSet = false; +function setGlobalContext(context) { + if (DEBUG) { + if (globalContextWasSet) { + throw new Error('Attempted to set the global context twice. This should only be set once.'); + } + + globalContextWasSet = true; + } + + scheduleRevalidate = context.scheduleRevalidate; + scheduleDestroy = context.scheduleDestroy; + scheduleDestroyed = context.scheduleDestroyed; + toIterator = context.toIterator; + toBool = context.toBool; + getProp = context.getProp; + setProp = context.setProp; + getPath = context.getPath; + setPath = context.setPath; + warnIfStyleNotTrusted = context.warnIfStyleNotTrusted; + assert = context.assert; + deprecate = context.deprecate; +} +let assertGlobalContextWasSet; +let testOverrideGlobalContext; + +if (DEBUG) { + assertGlobalContextWasSet = () => { + if (globalContextWasSet === false) { + throw new Error('The global context for Glimmer VM was not set. You must set these global context functions to let Glimmer VM know how to accomplish certain operations. You can do this by importing `setGlobalContext` from `@glimmer/global-context`'); + } + }; + + testOverrideGlobalContext = context => { + let originalGlobalContext = globalContextWasSet ? { + scheduleRevalidate, + scheduleDestroy, + scheduleDestroyed, + toIterator, + toBool, + getProp, + setProp, + getPath, + setPath, + warnIfStyleNotTrusted, + assert, + deprecate + } : null; + + if (context === null) { + globalContextWasSet = false; + } else { + globalContextWasSet = true; + } // We use `undefined as any` here to unset the values when resetting the + // context at the end of a test. + + + scheduleRevalidate = (context === null || context === void 0 ? void 0 : context.scheduleRevalidate) || undefined; + scheduleDestroy = (context === null || context === void 0 ? void 0 : context.scheduleDestroy) || undefined; + scheduleDestroyed = (context === null || context === void 0 ? void 0 : context.scheduleDestroyed) || undefined; + toIterator = (context === null || context === void 0 ? void 0 : context.toIterator) || undefined; + toBool = (context === null || context === void 0 ? void 0 : context.toBool) || undefined; + getProp = (context === null || context === void 0 ? void 0 : context.getProp) || undefined; + setProp = (context === null || context === void 0 ? void 0 : context.setProp) || undefined; + getPath = (context === null || context === void 0 ? void 0 : context.getPath) || undefined; + setPath = (context === null || context === void 0 ? void 0 : context.setPath) || undefined; + warnIfStyleNotTrusted = (context === null || context === void 0 ? void 0 : context.warnIfStyleNotTrusted) || undefined; + assert = (context === null || context === void 0 ? void 0 : context.assert) || undefined; + deprecate = (context === null || context === void 0 ? void 0 : context.deprecate) || undefined; + return originalGlobalContext; + }; +} + +export default setGlobalContext; +export { scheduleRevalidate, scheduleDestroy, scheduleDestroyed, toIterator, toBool, getProp, setProp, getPath, setPath, warnIfStyleNotTrusted, assert, deprecate, assertGlobalContextWasSet, testOverrideGlobalContext }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/low-level.js b/ember-vendored-pr-19806/dependencies/@glimmer/low-level.js new file mode 100644 index 0000000..68af922 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/low-level.js @@ -0,0 +1,77 @@ +class Storage { + constructor() { + this.array = []; + this.next = 0; + } + + add(element) { + let { + next: slot, + array + } = this; + + if (slot === array.length) { + this.next++; + } else { + let prev = array[slot]; + this.next = prev; + } + + this.array[slot] = element; + return slot; + } + + deref(pointer) { + return this.array[pointer]; + } + + drop(pointer) { + this.array[pointer] = this.next; + this.next = pointer; + } + +} + +class Stack { + constructor(vec = []) { + this.vec = vec; + } + + clone() { + return new Stack(this.vec.slice()); + } + + sliceFrom(start) { + return new Stack(this.vec.slice(start)); + } + + slice(start, end) { + return new Stack(this.vec.slice(start, end)); + } + + copy(from, to) { + this.vec[to] = this.vec[from]; + } // TODO: how to model u64 argument? + + + writeRaw(pos, value) { + // TODO: Grow? + this.vec[pos] = value; + } // TODO: partially decoded enum? + + + getRaw(pos) { + return this.vec[pos]; + } + + reset() { + this.vec.length = 0; + } + + len() { + return this.vec.length; + } + +} + +export { Storage, Stack }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/manager.js b/ember-vendored-pr-19806/dependencies/@glimmer/manager.js new file mode 100644 index 0000000..ab18af9 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/manager.js @@ -0,0 +1,906 @@ +import { DEBUG } from '@glimmer/env'; +import { debugToString, _WeakSet, HAS_NATIVE_PROXY, assign, dict } from '@glimmer/util'; +import { valueForRef, createConstRef, createComputeRef, UNDEFINED_REFERENCE } from '@glimmer/reference'; +import { track, deprecateMutationsInTrackingTransaction, createUpdatableTag, untrack } from '@glimmer/validator'; +import { registerDestructor, associateDestroyableChild } from '@glimmer/destroyable'; +import { setOwner } from '@glimmer/owner'; + +const COMPONENT_MANAGERS = new WeakMap(); +const MODIFIER_MANAGERS = new WeakMap(); +const HELPER_MANAGERS = new WeakMap(); /////////// + +const getPrototypeOf = Object.getPrototypeOf; + +function setManager(map, manager, obj) { + if (DEBUG && (typeof obj !== 'object' || obj === null) && typeof obj !== 'function') { + throw new Error(`Attempted to set a manager on a non-object value. Managers can only be associated with objects or functions. Value was ${debugToString(obj)}`); + } + + if (DEBUG && map.has(obj)) { + throw new Error(`Attempted to set the same type of manager multiple times on a value. You can only associate one manager of each type with a given value. Value was ${debugToString(obj)}`); + } + + map.set(obj, manager); + return obj; +} + +function getManager(map, obj) { + let pointer = obj; + + while (pointer !== undefined && pointer !== null) { + const manager = map.get(pointer); + + if (manager !== undefined) { + return manager; + } + + pointer = getPrototypeOf(pointer); + } + + return undefined; +} /////////// + + +function setInternalModifierManager(manager, definition) { + return setManager(MODIFIER_MANAGERS, manager, definition); +} +function getInternalModifierManager(definition, isOptional) { + if (DEBUG && typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) { + throw new Error(`Attempted to use a value as a modifier, but it was not an object or function. Modifier definitions must be objects or functions with an associated modifier manager. The value was: ${definition}`); + } + + const manager = getManager(MODIFIER_MANAGERS, definition); + + if (manager === undefined) { + if (isOptional === true) { + return null; + } else if (DEBUG) { + throw new Error(`Attempted to load a modifier, but there wasn't a modifier manager associated with the definition. The definition was: ${debugToString(definition)}`); + } + } + + return manager; +} +function setInternalHelperManager(manager, definition) { + return setManager(HELPER_MANAGERS, manager, definition); +} +function getInternalHelperManager(definition, isOptional) { + if (DEBUG && typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) { + throw new Error(`Attempted to use a value as a helper, but it was not an object or function. Helper definitions must be objects or functions with an associated helper manager. The value was: ${definition}`); + } + + const manager = getManager(HELPER_MANAGERS, definition); + + if (manager === undefined) { + if (isOptional === true) { + return null; + } else if (DEBUG) { + throw new Error(`Attempted to load a helper, but there wasn't a helper manager associated with the definition. The definition was: ${debugToString(definition)}`); + } + } + + return manager; +} +function setInternalComponentManager(factory, obj) { + return setManager(COMPONENT_MANAGERS, factory, obj); +} +function getInternalComponentManager(definition, isOptional) { + if (DEBUG && typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) { + throw new Error(`Attempted to use a value as a component, but it was not an object or function. Component definitions must be objects or functions with an associated component manager. The value was: ${definition}`); + } + + const manager = getManager(COMPONENT_MANAGERS, definition); + + if (manager === undefined) { + if (isOptional === true) { + return null; + } else if (DEBUG) { + throw new Error(`Attempted to load a component, but there wasn't a component manager associated with the definition. The definition was: ${debugToString(definition)}`); + } + } + + return manager; +} /////////// + +function hasInternalComponentManager(definition) { + return getManager(COMPONENT_MANAGERS, definition) !== undefined; +} +function hasInternalHelperManager(definition) { + return getManager(HELPER_MANAGERS, definition) !== undefined; +} +function hasInternalModifierManager(definition) { + return getManager(MODIFIER_MANAGERS, definition) !== undefined; +} + +const FROM_CAPABILITIES = DEBUG ? new _WeakSet() : undefined; +function buildCapabilities(capabilities) { + if (DEBUG) { + FROM_CAPABILITIES.add(capabilities); + Object.freeze(capabilities); + } + + return capabilities; +} +/** + * Converts a ComponentCapabilities object into a 32-bit integer representation. + */ + +function capabilityFlagsFrom(capabilities) { + return 0 | (capabilities.dynamicLayout ? 1 + /* DynamicLayout */ + : 0) | (capabilities.dynamicTag ? 2 + /* DynamicTag */ + : 0) | (capabilities.prepareArgs ? 4 + /* PrepareArgs */ + : 0) | (capabilities.createArgs ? 8 + /* CreateArgs */ + : 0) | (capabilities.attributeHook ? 16 + /* AttributeHook */ + : 0) | (capabilities.elementHook ? 32 + /* ElementHook */ + : 0) | (capabilities.dynamicScope ? 64 + /* DynamicScope */ + : 0) | (capabilities.createCaller ? 128 + /* CreateCaller */ + : 0) | (capabilities.updateHook ? 256 + /* UpdateHook */ + : 0) | (capabilities.createInstance ? 512 + /* CreateInstance */ + : 0) | (capabilities.wrapped ? 1024 + /* Wrapped */ + : 0) | (capabilities.willDestroy ? 2048 + /* WillDestroy */ + : 0) | (capabilities.hasSubOwner ? 4096 + /* HasSubOwner */ + : 0); +} +function managerHasCapability(_manager, capabilities, capability) { + return !!(capabilities & capability); +} +function hasCapability(capabilities, capability) { + return !!(capabilities & capability); +} + +const CUSTOM_TAG_FOR = new WeakMap(); +function getCustomTagFor(obj) { + return CUSTOM_TAG_FOR.get(obj); +} +function setCustomTagFor(obj, customTagFn) { + CUSTOM_TAG_FOR.set(obj, customTagFn); +} + +function convertToInt(prop) { + if (typeof prop === 'symbol') return null; + const num = Number(prop); + if (isNaN(num)) return null; + return num % 1 === 0 ? num : null; +} + +function tagForNamedArg(namedArgs, key) { + return track(() => { + if (key in namedArgs) { + valueForRef(namedArgs[key]); + } + }); +} + +function tagForPositionalArg(positionalArgs, key) { + return track(() => { + if (key === '[]') { + // consume all of the tags in the positional array + positionalArgs.forEach(valueForRef); + } + + const parsed = convertToInt(key); + + if (parsed !== null && parsed < positionalArgs.length) { + // consume the tag of the referenced index + valueForRef(positionalArgs[parsed]); + } + }); +} + +let argsProxyFor; + +class NamedArgsProxy { + constructor(named) { + this.named = named; + } + + get(_target, prop) { + const ref = this.named[prop]; + + if (ref !== undefined) { + return valueForRef(ref); + } + } + + has(_target, prop) { + return prop in this.named; + } + + ownKeys() { + return Object.keys(this.named); + } + + isExtensible() { + return false; + } + + getOwnPropertyDescriptor(_target, prop) { + if (DEBUG && !(prop in this.named)) { + throw new Error(`args proxies do not have real property descriptors, so you should never need to call getOwnPropertyDescriptor yourself. This code exists for enumerability, such as in for-in loops and Object.keys(). Attempted to get the descriptor for \`${String(prop)}\``); + } + + return { + enumerable: true, + configurable: true + }; + } + +} + +class PositionalArgsProxy { + constructor(positional) { + this.positional = positional; + } + + get(target, prop) { + let { + positional + } = this; + + if (prop === 'length') { + return positional.length; + } + + const parsed = convertToInt(prop); + + if (parsed !== null && parsed < positional.length) { + return valueForRef(positional[parsed]); + } + + return target[prop]; + } + + isExtensible() { + return false; + } + + has(_target, prop) { + const parsed = convertToInt(prop); + return parsed !== null && parsed < this.positional.length; + } + +} + +if (HAS_NATIVE_PROXY) { + argsProxyFor = (capturedArgs, type) => { + const { + named, + positional + } = capturedArgs; + + let getNamedTag = (_obj, key) => tagForNamedArg(named, key); + + let getPositionalTag = (_obj, key) => tagForPositionalArg(positional, key); + + const namedHandler = new NamedArgsProxy(named); + const positionalHandler = new PositionalArgsProxy(positional); + const namedTarget = Object.create(null); + const positionalTarget = []; + + if (DEBUG) { + const setHandler = function (_target, prop) { + throw new Error(`You attempted to set ${String(prop)} on the arguments of a component, helper, or modifier. Arguments are immutable and cannot be updated directly, they always represent the values that is passed down. If you want to set default values, you should use a getter and local tracked state instead.`); + }; + + const forInDebugHandler = () => { + throw new Error(`Object.keys() was called on the positional arguments array for a ${type}, which is not supported. This function is a low-level function that should not need to be called for positional argument arrays. You may be attempting to iterate over the array using for...in instead of for...of.`); + }; + + namedHandler.set = setHandler; + positionalHandler.set = setHandler; + positionalHandler.ownKeys = forInDebugHandler; + } + + const namedProxy = new Proxy(namedTarget, namedHandler); + const positionalProxy = new Proxy(positionalTarget, positionalHandler); + setCustomTagFor(namedProxy, getNamedTag); + setCustomTagFor(positionalProxy, getPositionalTag); + return { + named: namedProxy, + positional: positionalProxy + }; + }; +} else { + argsProxyFor = (capturedArgs, _type) => { + const { + named, + positional + } = capturedArgs; + + let getNamedTag = (_obj, key) => tagForNamedArg(named, key); + + let getPositionalTag = (_obj, key) => tagForPositionalArg(positional, key); + + let namedProxy = {}; + let positionalProxy = []; + setCustomTagFor(namedProxy, getNamedTag); + setCustomTagFor(positionalProxy, getPositionalTag); + Object.keys(named).forEach(name => { + Object.defineProperty(namedProxy, name, { + enumerable: true, + configurable: true, + + get() { + return valueForRef(named[name]); + } + + }); + }); + positional.forEach((ref, index) => { + Object.defineProperty(positionalProxy, index, { + enumerable: true, + configurable: true, + + get() { + return valueForRef(ref); + } + + }); + }); + + if (DEBUG) { + // Prevent mutations in development mode. This will not prevent the + // proxy from updating, but will prevent assigning new values or pushing + // for instance. + Object.freeze(namedProxy); + Object.freeze(positionalProxy); + } + + return { + named: namedProxy, + positional: positionalProxy + }; + }; +} + +const CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: true, + attributeHook: false, + elementHook: false, + createCaller: false, + dynamicScope: true, + updateHook: true, + createInstance: true, + wrapped: false, + willDestroy: false, + hasSubOwner: false +}; +function componentCapabilities(managerAPI, options = {}) { + if (DEBUG && managerAPI !== '3.4' && managerAPI !== '3.13') { + throw new Error('Invalid component manager compatibility specified'); + } + + let updateHook = true; + + if (managerAPI === '3.13') { + updateHook = Boolean(options.updateHook); + } + + return buildCapabilities({ + asyncLifeCycleCallbacks: Boolean(options.asyncLifecycleCallbacks), + destructor: Boolean(options.destructor), + updateHook + }); +} +function hasAsyncLifeCycleCallbacks(delegate) { + return delegate.capabilities.asyncLifeCycleCallbacks; +} +function hasUpdateHook(delegate) { + return delegate.capabilities.updateHook; +} +function hasAsyncUpdateHook(delegate) { + return hasAsyncLifeCycleCallbacks(delegate) && hasUpdateHook(delegate); +} +function hasDestructors(delegate) { + return delegate.capabilities.destructor; +} +/** + The CustomComponentManager allows addons to provide custom component + implementations that integrate seamlessly into Ember. This is accomplished + through a delegate, registered with the custom component manager, which + implements a set of hooks that determine component behavior. + + To create a custom component manager, instantiate a new CustomComponentManager + class and pass the delegate as the first argument: + + ```js + let manager = new CustomComponentManager({ + // ...delegate implementation... + }); + ``` + + ## Delegate Hooks + + Throughout the lifecycle of a component, the component manager will invoke + delegate hooks that are responsible for surfacing those lifecycle changes to + the end developer. + + * `create()` - invoked when a new instance of a component should be created + * `update()` - invoked when the arguments passed to a component change + * `getContext()` - returns the object that should be +*/ + +class CustomComponentManager { + constructor(factory) { + this.factory = factory; + this.componentManagerDelegates = new WeakMap(); + } + + getDelegateFor(owner) { + let { + componentManagerDelegates + } = this; + let delegate = componentManagerDelegates.get(owner); + + if (delegate === undefined) { + let { + factory + } = this; + delegate = factory(owner); + + if (DEBUG && !FROM_CAPABILITIES.has(delegate.capabilities)) { + // TODO: This error message should make sense in both Ember and Glimmer https://github.com/glimmerjs/glimmer-vm/issues/1200 + throw new Error(`Custom component managers must have a \`capabilities\` property that is the result of calling the \`capabilities('3.4' | '3.13')\` (imported via \`import { capabilities } from '@ember/component';\`). Received: \`${JSON.stringify(delegate.capabilities)}\` for: \`${delegate}\``); + } + + componentManagerDelegates.set(owner, delegate); + } + + return delegate; + } + + create(owner, definition, vmArgs) { + let delegate = this.getDelegateFor(owner); + let args = argsProxyFor(vmArgs.capture(), 'component'); + let component; + + if (DEBUG && deprecateMutationsInTrackingTransaction !== undefined) { + deprecateMutationsInTrackingTransaction(() => { + component = delegate.createComponent(definition, args); + }); + } else { + component = delegate.createComponent(definition, args); + } + + return new CustomComponentState(component, delegate, args); + } + + getDebugName(definition) { + return typeof definition === 'function' ? definition.name : definition.toString(); + } + + update(bucket) { + let { + delegate + } = bucket; + + if (hasUpdateHook(delegate)) { + let { + component, + args + } = bucket; + delegate.updateComponent(component, args); + } + } + + didCreate({ + component, + delegate + }) { + if (hasAsyncLifeCycleCallbacks(delegate)) { + delegate.didCreateComponent(component); + } + } + + didUpdate({ + component, + delegate + }) { + if (hasAsyncUpdateHook(delegate)) { + delegate.didUpdateComponent(component); + } + } + + didRenderLayout() {} + + didUpdateLayout() {} + + getSelf({ + component, + delegate + }) { + return createConstRef(delegate.getContext(component), 'this'); + } + + getDestroyable(bucket) { + const { + delegate + } = bucket; + + if (hasDestructors(delegate)) { + const { + component + } = bucket; + registerDestructor(bucket, () => delegate.destroyComponent(component)); + return bucket; + } + + return null; + } + + getCapabilities() { + return CAPABILITIES; + } + +} +/** + * Stores internal state about a component instance after it's been created. + */ + +class CustomComponentState { + constructor(component, delegate, args) { + this.component = component; + this.delegate = delegate; + this.args = args; + } + +} + +function modifierCapabilities(managerAPI, optionalFeatures = {}) { + if (DEBUG && managerAPI !== '3.13' && managerAPI !== '3.22') { + throw new Error('Invalid modifier manager compatibility specified'); + } + + return buildCapabilities({ + disableAutoTracking: Boolean(optionalFeatures.disableAutoTracking), + useArgsProxy: managerAPI === '3.13' ? false : true, + // This capability is used in Ember, exclusively in resolution mode. See the + // Ember glimmer resolver for details. + passFactoryToCreate: managerAPI === '3.13' + }); +} +/** + The CustomModifierManager allows addons to provide custom modifier + implementations that integrate seamlessly into Ember. This is accomplished + through a delegate, registered with the custom modifier manager, which + implements a set of hooks that determine modifier behavior. + To create a custom modifier manager, instantiate a new CustomModifierManager + class and pass the delegate as the first argument: + + ```js + let manager = new CustomModifierManager({ + // ...delegate implementation... + }); + ``` + + ## Delegate Hooks + + Throughout the lifecycle of a modifier, the modifier manager will invoke + delegate hooks that are responsible for surfacing those lifecycle changes to + the end developer. + * `createModifier()` - invoked when a new instance of a modifier should be created + * `installModifier()` - invoked when the modifier is installed on the element + * `updateModifier()` - invoked when the arguments passed to a modifier change + * `destroyModifier()` - invoked when the modifier is about to be destroyed +*/ + +class CustomModifierManager { + constructor(factory) { + this.factory = factory; + this.componentManagerDelegates = new WeakMap(); + } + + getDelegateFor(owner) { + let { + componentManagerDelegates + } = this; + let delegate = componentManagerDelegates.get(owner); + + if (delegate === undefined) { + let { + factory + } = this; + delegate = factory(owner); + + if (DEBUG && !FROM_CAPABILITIES.has(delegate.capabilities)) { + // TODO: This error message should make sense in both Ember and Glimmer https://github.com/glimmerjs/glimmer-vm/issues/1200 + throw new Error(`Custom modifier managers must have a \`capabilities\` property that is the result of calling the \`capabilities('3.13' | '3.22')\` (imported via \`import { capabilities } from '@ember/modifier';\`). Received: \`${JSON.stringify(delegate.capabilities)}\` for: \`${delegate}\``); + } + + componentManagerDelegates.set(owner, delegate); + } + + return delegate; + } + + create(owner, element, definition, capturedArgs) { + let delegate = this.getDelegateFor(owner); + let { + useArgsProxy, + passFactoryToCreate + } = delegate.capabilities; + let argsProxy = argsProxyFor(capturedArgs, 'modifier'); + let args = useArgsProxy ? argsProxy : reifyArgs(capturedArgs); + let instance; + let factoryOrDefinition = definition; + + if (passFactoryToCreate) { + // Make a fake factory. While not perfect, this should generally prevent + // breakage in users of older modifier capabilities. + factoryOrDefinition = { + create(args) { + let params = assign({}, args); + setOwner(params, owner); + return definition.create(args); + }, + + class: definition + }; + } + + if (DEBUG && deprecateMutationsInTrackingTransaction !== undefined) { + deprecateMutationsInTrackingTransaction(() => { + instance = delegate.createModifier(factoryOrDefinition, args); + }); + } else { + instance = delegate.createModifier(factoryOrDefinition, args); + } + + let tag = createUpdatableTag(); + let state; + + if (useArgsProxy) { + state = { + tag, + element, + delegate, + args, + modifier: instance + }; + } else { + state = { + tag, + element, + modifier: instance, + delegate, + + get args() { + return reifyArgs(capturedArgs); + } + + }; + } + + if (DEBUG) { + state.debugName = typeof definition === 'function' ? definition.name : definition.toString(); + } + + registerDestructor(state, () => delegate.destroyModifier(instance, argsProxy)); + return state; + } + + getDebugName({ + debugName + }) { + return debugName; + } + + getTag({ + tag + }) { + return tag; + } + + install({ + element, + args, + modifier, + delegate + }) { + let { + capabilities + } = delegate; + + if (capabilities.disableAutoTracking === true) { + untrack(() => delegate.installModifier(modifier, element, args)); + } else { + delegate.installModifier(modifier, element, args); + } + } + + update({ + args, + modifier, + delegate + }) { + let { + capabilities + } = delegate; + + if (capabilities.disableAutoTracking === true) { + untrack(() => delegate.updateModifier(modifier, args)); + } else { + delegate.updateModifier(modifier, args); + } + } + + getDestroyable(state) { + return state; + } + +} +function reifyArgs({ + named, + positional +}) { + let reifiedNamed = dict(); + + for (let key in named) { + reifiedNamed[key] = valueForRef(named[key]); + } + + let reifiedPositional = positional.map(valueForRef); + return { + named: reifiedNamed, + positional: reifiedPositional + }; +} + +function helperCapabilities(managerAPI, options = {}) { + if (DEBUG && managerAPI !== '3.23') { + throw new Error('Invalid helper manager compatibility specified'); + } + + if (DEBUG && (!(options.hasValue || options.hasScheduledEffect) || options.hasValue && options.hasScheduledEffect)) { + throw new Error('You must pass either the `hasValue` OR the `hasScheduledEffect` capability when defining a helper manager. Passing neither, or both, is not permitted.'); + } + + if (DEBUG && options.hasScheduledEffect) { + throw new Error('The `hasScheduledEffect` capability has not yet been implemented for helper managers. Please pass `hasValue` instead'); + } + + return buildCapabilities({ + hasValue: Boolean(options.hasValue), + hasDestroyable: Boolean(options.hasDestroyable), + hasScheduledEffect: Boolean(options.hasScheduledEffect) + }); +} //////////// + +function hasValue(manager) { + return manager.capabilities.hasValue; +} +function hasDestroyable(manager) { + return manager.capabilities.hasDestroyable; +} //////////// + +class CustomHelperManager { + constructor(factory) { + this.factory = factory; + this.helperManagerDelegates = new WeakMap(); + this.undefinedDelegate = null; + } + + getDelegateForOwner(owner) { + let delegate = this.helperManagerDelegates.get(owner); + + if (delegate === undefined) { + let { + factory + } = this; + delegate = factory(owner); + + if (DEBUG && !FROM_CAPABILITIES.has(delegate.capabilities)) { + // TODO: This error message should make sense in both Ember and Glimmer https://github.com/glimmerjs/glimmer-vm/issues/1200 + throw new Error(`Custom helper managers must have a \`capabilities\` property that is the result of calling the \`capabilities('3.23')\` (imported via \`import { capabilities } from '@ember/helper';\`). Received: \`${JSON.stringify(delegate.capabilities)}\` for: \`${delegate}\``); + } + + this.helperManagerDelegates.set(owner, delegate); + } + + return delegate; + } + + getDelegateFor(owner) { + if (owner === undefined) { + let { + undefinedDelegate + } = this; + + if (undefinedDelegate === null) { + let { + factory + } = this; + this.undefinedDelegate = undefinedDelegate = factory(undefined); + } + + return undefinedDelegate; + } else { + return this.getDelegateForOwner(owner); + } + } + + getHelper(definition) { + return (capturedArgs, owner) => { + var _a, _b; + + let manager = this.getDelegateFor(owner); + const args = argsProxyFor(capturedArgs, 'helper'); + const bucket = manager.createHelper(definition, args); + + if (hasValue(manager)) { + let cache = createComputeRef(() => manager.getValue(bucket), null, DEBUG && manager.getDebugName && manager.getDebugName(definition)); + + if (hasDestroyable(manager)) { + associateDestroyableChild(cache, manager.getDestroyable(bucket)); + } + + return cache; + } else if (hasDestroyable(manager)) { + let ref = createConstRef(undefined, DEBUG && ((_b = (_a = manager.getDebugName) === null || _a === void 0 ? void 0 : _a.call(manager, definition)) !== null && _b !== void 0 ? _b : 'unknown helper')); + associateDestroyableChild(ref, manager.getDestroyable(bucket)); + return ref; + } else { + return UNDEFINED_REFERENCE; + } + }; + } + +} + +function setComponentManager(factory, obj) { + return setInternalComponentManager(new CustomComponentManager(factory), obj); +} +function setModifierManager(factory, obj) { + return setInternalModifierManager(new CustomModifierManager(factory), obj); +} +function setHelperManager(factory, obj) { + return setInternalHelperManager(new CustomHelperManager(factory), obj); +} + +const TEMPLATES = new WeakMap(); +const getPrototypeOf$1 = Object.getPrototypeOf; +function setComponentTemplate(factory, obj) { + if (DEBUG && !(obj !== null && (typeof obj === 'object' || typeof obj === 'function'))) { + throw new Error(`Cannot call \`setComponentTemplate\` on \`${debugToString(obj)}\``); + } + + if (DEBUG && TEMPLATES.has(obj)) { + throw new Error(`Cannot call \`setComponentTemplate\` multiple times on the same class (\`${debugToString(obj)}\`)`); + } + + TEMPLATES.set(obj, factory); + return obj; +} +function getComponentTemplate(obj) { + let pointer = obj; + + while (pointer !== null) { + let template = TEMPLATES.get(pointer); + + if (template !== undefined) { + return template; + } + + pointer = getPrototypeOf$1(pointer); + } + + return undefined; +} + +export { setInternalHelperManager, setInternalModifierManager, setInternalComponentManager, getInternalHelperManager, getInternalModifierManager, getInternalComponentManager, hasInternalHelperManager, hasInternalModifierManager, hasInternalComponentManager, setHelperManager, setModifierManager, setComponentManager, componentCapabilities, CustomComponentManager, modifierCapabilities, CustomModifierManager, helperCapabilities, hasDestroyable, hasValue, CustomHelperManager, getComponentTemplate, setComponentTemplate, capabilityFlagsFrom, hasCapability, managerHasCapability, getCustomTagFor, setCustomTagFor }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/node.js b/ember-vendored-pr-19806/dependencies/@glimmer/node.js new file mode 100644 index 0000000..9dd2fd3 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/node.js @@ -0,0 +1,173 @@ +import { ConcreteBounds, DOMTreeConstruction, NewElementBuilder } from '@glimmer/runtime'; +import createHTMLDocument from '@simple-dom/document'; + +class NodeDOMTreeConstruction extends DOMTreeConstruction { + constructor(doc) { + super(doc || createHTMLDocument()); + } // override to prevent usage of `this.document` until after the constructor + + + setupUselessElement() {} + + insertHTMLBefore(parent, reference, html) { + let raw = this.document.createRawHTMLSection(html); + parent.insertBefore(raw, reference); + return new ConcreteBounds(parent, raw, raw); + } // override to avoid SVG detection/work when in node (this is not needed in SSR) + + + createElement(tag) { + return this.document.createElement(tag); + } // override to avoid namespace shenanigans when in node (this is not needed in SSR) + + + setAttribute(element, name, value) { + element.setAttribute(name, value); + } + +} + +const TEXT_NODE = 3; +const NEEDS_EXTRA_CLOSE = new WeakMap(); + +function currentNode(cursor) { + let { + element, + nextSibling + } = cursor; + + if (nextSibling === null) { + return element.lastChild; + } else { + return nextSibling.previousSibling; + } +} + +class SerializeBuilder extends NewElementBuilder { + constructor() { + super(...arguments); + this.serializeBlockDepth = 0; + } + + __openBlock() { + let { + tagName + } = this.element; + + if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') { + let depth = this.serializeBlockDepth++; + + this.__appendComment(`%+b:${depth}%`); + } + + super.__openBlock(); + } + + __closeBlock() { + let { + tagName + } = this.element; + + super.__closeBlock(); + + if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') { + let depth = --this.serializeBlockDepth; + + this.__appendComment(`%-b:${depth}%`); + } + } + + __appendHTML(html) { + let { + tagName + } = this.element; + + if (tagName === 'TITLE' || tagName === 'SCRIPT' || tagName === 'STYLE') { + return super.__appendHTML(html); + } // Do we need to run the html tokenizer here? + + + let first = this.__appendComment('%glmr%'); + + if (tagName === 'TABLE') { + let openIndex = html.indexOf('<'); + + if (openIndex > -1) { + let tr = html.slice(openIndex + 1, openIndex + 3); + + if (tr === 'tr') { + html = `${html}`; + } + } + } + + if (html === '') { + this.__appendComment('% %'); + } else { + super.__appendHTML(html); + } + + let last = this.__appendComment('%glmr%'); + + return new ConcreteBounds(this.element, first, last); + } + + __appendText(string) { + let { + tagName + } = this.element; + let current = currentNode(this); + + if (tagName === 'TITLE' || tagName === 'SCRIPT' || tagName === 'STYLE') { + return super.__appendText(string); + } else if (string === '') { + return this.__appendComment('% %'); + } else if (current && current.nodeType === TEXT_NODE) { + this.__appendComment('%|%'); + } + + return super.__appendText(string); + } + + closeElement() { + if (NEEDS_EXTRA_CLOSE.has(this.element)) { + NEEDS_EXTRA_CLOSE.delete(this.element); + super.closeElement(); + } + + return super.closeElement(); + } + + openElement(tag) { + if (tag === 'tr') { + if (this.element.tagName !== 'TBODY' && this.element.tagName !== 'THEAD' && this.element.tagName !== 'TFOOT') { + this.openElement('tbody'); // This prevents the closeBlock comment from being re-parented + // under the auto inserted tbody. Rehydration builder needs to + // account for the insertion since it is injected here and not + // really in the template. + + NEEDS_EXTRA_CLOSE.set(this.constructing, true); + this.flushElement(null); + } + } + + return super.openElement(tag); + } + + pushRemoteElement(element, cursorId, insertBefore = null) { + let { + dom + } = this; + let script = dom.createElement('script'); + script.setAttribute('glmr', cursorId); + dom.insertBefore(element, script, insertBefore); + return super.pushRemoteElement(element, cursorId, insertBefore); + } + +} + +function serializeBuilder(env, cursor) { + return SerializeBuilder.forInitialRender(env, cursor); +} + +export { NodeDOMTreeConstruction, serializeBuilder }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/opcode-compiler.js b/ember-vendored-pr-19806/dependencies/@glimmer/opcode-compiler.js new file mode 100644 index 0000000..5bd7c8b --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/opcode-compiler.js @@ -0,0 +1,3141 @@ +import { dict, assign, isSmallInt, debugToString, EMPTY_ARRAY, EMPTY_STRING_ARRAY, encodeImmediate, Stack, encodeHandle, unwrapTemplate } from '@glimmer/util'; +import { DEBUG } from '@glimmer/env'; +import { $v0, $fp, $s0, $s1, $sp, isMachineOp } from '@glimmer/vm'; +import { assert, deprecate } from '@glimmer/global-context'; +import { hasCapability } from '@glimmer/manager'; +import { InstructionEncoderImpl } from '@glimmer/encoder'; + +class NamedBlocksImpl { + constructor(blocks) { + this.blocks = blocks; + this.names = blocks ? Object.keys(blocks) : []; + } + + get(name) { + if (!this.blocks) return null; + return this.blocks[name] || null; + } + + has(name) { + let { + blocks + } = this; + return blocks !== null && name in blocks; + } + + with(name, block) { + let { + blocks + } = this; + + if (blocks) { + return new NamedBlocksImpl(assign({}, blocks, { + [name]: block + })); + } else { + return new NamedBlocksImpl({ + [name]: block + }); + } + } + + get hasAny() { + return this.blocks !== null; + } + +} +const EMPTY_BLOCKS = new NamedBlocksImpl(null); +function namedBlocks(blocks) { + if (blocks === null) { + return EMPTY_BLOCKS; + } + + let out = dict(); + let [keys, values] = blocks; + + for (let i = 0; i < keys.length; i++) { + out[keys[i]] = values[i]; + } + + return new NamedBlocksImpl(out); +} + +function labelOperand(value) { + return { + type: 1 + /* Label */ + , + value + }; +} +function evalSymbolsOperand() { + return { + type: 3 + /* EvalSymbols */ + , + value: undefined + }; +} +function isStrictMode() { + return { + type: 2 + /* IsStrictMode */ + , + value: undefined + }; +} +function blockOperand(value) { + return { + type: 4 + /* Block */ + , + value + }; +} +function stdlibOperand(value) { + return { + type: 5 + /* StdLib */ + , + value + }; +} +function nonSmallIntOperand(value) { + return { + type: 6 + /* NonSmallInt */ + , + value + }; +} +function symbolTableOperand(value) { + return { + type: 7 + /* SymbolTable */ + , + value + }; +} +function layoutOperand(value) { + return { + type: 8 + /* Layout */ + , + value + }; +} + +function isGetLikeTuple(opcode) { + return Array.isArray(opcode) && opcode.length === 2; +} + +function makeResolutionTypeVerifier(typeToVerify) { + return opcode => { + if (!isGetLikeTuple(opcode)) return false; + let type = opcode[0]; + return type === 31 + /* GetStrictFree */ + || type === 32 + /* GetTemplateSymbol */ + || type === typeToVerify; + }; +} + +const isGetFreeComponent = makeResolutionTypeVerifier(39 +/* GetFreeAsComponentHead */ +); +const isGetFreeModifier = makeResolutionTypeVerifier(38 +/* GetFreeAsModifierHead */ +); +const isGetFreeHelper = makeResolutionTypeVerifier(37 +/* GetFreeAsHelperHead */ +); +const isGetFreeComponentOrHelper = makeResolutionTypeVerifier(35 +/* GetFreeAsComponentOrHelperHead */ +); +const isGetFreeOptionalComponentOrHelper = makeResolutionTypeVerifier(34 +/* GetFreeAsComponentOrHelperHeadOrThisFallback */ +); + +function assertResolverInvariants(meta) { + if (DEBUG) { + if (!meta.upvars) { + throw new Error('Attempted to resolve a component, helper, or modifier, but no free vars were found'); + } + + if (!meta.owner) { + throw new Error('Attempted to resolve a component, helper, or modifier, but no owner was associated with the template it was being resolved from'); + } + } + + return meta; +} +/** + * + * + * + */ + + +function resolveComponent(resolver, constants, meta, [, expr, then]) { + let type = expr[0]; + + if (DEBUG && expr[0] === 31 + /* GetStrictFree */ + ) { + throw new Error(`Attempted to resolve a component in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]]}`); + } + + if (type === 32 + /* GetTemplateSymbol */ + ) { + let { + scopeValues, + owner + } = meta; + let definition = scopeValues[expr[1]]; + then(constants.component(definition, owner)); + } else { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let definition = resolver.lookupComponent(name, owner); + + if (DEBUG && (typeof definition !== 'object' || definition === null)) { + throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`); + } + + then(constants.resolvedComponent(definition, name)); + } +} +/** + * (helper) + * (helper arg) + */ + +function resolveHelper(resolver, constants, meta, [, expr, then]) { + let type = expr[0]; + + if (type === 32 + /* GetTemplateSymbol */ + ) { + let { + scopeValues + } = meta; + let definition = scopeValues[expr[1]]; + then(constants.helper(definition)); + } else if (type === 31 + /* GetStrictFree */ + ) { + then(lookupBuiltInHelper(expr, resolver, meta, constants, 'helper')); + } else { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let helper = resolver.lookupHelper(name, owner); + + if (DEBUG && helper === null) { + throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a helper, but nothing was found.`); + } + + then(constants.helper(helper, name)); + } +} +/** + *
+ *
+ * + */ + +function resolveModifier(resolver, constants, meta, [, expr, then]) { + let type = expr[0]; + + if (type === 32 + /* GetTemplateSymbol */ + ) { + let { + scopeValues + } = meta; + let definition = scopeValues[expr[1]]; + then(constants.modifier(definition)); + } else if (type === 31 + /* GetStrictFree */ + ) { + let { + upvars + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let modifier = resolver.lookupBuiltInModifier(name); + + if (DEBUG && modifier === null) { + throw new Error(`Attempted to resolve a modifier in a strict mode template, but it was not in scope: ${name}`); + } + + then(constants.modifier(modifier, name)); + } else { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let modifier = resolver.lookupModifier(name, owner); + + if (DEBUG && modifier === null) { + throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a modifier, but nothing was found.`); + } + + then(constants.modifier(modifier, name)); + } +} +/** + * {{component-or-helper arg}} + */ + +function resolveComponentOrHelper(resolver, constants, meta, [, expr, { + ifComponent, + ifHelper +}]) { + let type = expr[0]; + + if (type === 32 + /* GetTemplateSymbol */ + ) { + let { + scopeValues, + owner + } = meta; + let definition = scopeValues[expr[1]]; + let component = constants.component(definition, owner, true); + + if (component !== null) { + ifComponent(component); + return; + } + + let helper = constants.helper(definition, null, true); + + if (DEBUG && helper === null) { + throw new Error(`Attempted to use a value as either a component or helper, but it did not have a component manager or helper manager associated with it. The value was: ${debugToString(definition)}`); + } + + ifHelper(helper); + } else if (type === 31 + /* GetStrictFree */ + ) { + ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'component or helper')); + } else { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let definition = resolver.lookupComponent(name, owner); + + if (definition !== null) { + ifComponent(constants.resolvedComponent(definition, name)); + } else { + let helper = resolver.lookupHelper(name, owner); + + if (DEBUG && helper === null) { + throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component or helper, but nothing was found.`); + } + + ifHelper(constants.helper(helper, name)); + } + } +} +/** + * + */ + +function resolveOptionalHelper(resolver, constants, meta, [, expr, { + ifHelper, + ifFallback +}]) { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let helper = resolver.lookupHelper(name, owner); + + if (helper === null) { + ifFallback(name, meta.moduleName); + } else { + ifHelper(constants.helper(helper, name), name, meta.moduleName); + } +} +/** + * {{maybeHelperOrComponent}} + */ + +function resolveOptionalComponentOrHelper(resolver, constants, meta, [, expr, { + ifComponent, + ifHelper, + ifValue, + ifFallback +}]) { + let type = expr[0]; + + if (type === 32 + /* GetTemplateSymbol */ + ) { + let { + scopeValues, + owner + } = meta; + let definition = scopeValues[expr[1]]; + + if (typeof definition !== 'function' && (typeof definition !== 'object' || definition === null)) { + // The value is not an object, so it can't be a component or helper. + ifValue(constants.value(definition)); + return; + } + + let component = constants.component(definition, owner, true); + + if (component !== null) { + ifComponent(component); + return; + } + + let helper = constants.helper(definition, null, true); + + if (helper !== null) { + ifHelper(helper); + return; + } + + ifValue(constants.value(definition)); + } else if (type === 31 + /* GetStrictFree */ + ) { + ifHelper(lookupBuiltInHelper(expr, resolver, meta, constants, 'value')); + } else { + let { + upvars, + owner + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let definition = resolver.lookupComponent(name, owner); + + if (definition !== null) { + ifComponent(constants.resolvedComponent(definition, name)); + return; + } + + let helper = resolver.lookupHelper(name, owner); + + if (helper !== null) { + ifHelper(constants.helper(helper, name)); + return; + } + + ifFallback(name); + } +} + +function lookupBuiltInHelper(expr, resolver, meta, constants, type) { + let { + upvars + } = assertResolverInvariants(meta); + let name = upvars[expr[1]]; + let helper = resolver.lookupBuiltInHelper(name); + + if (DEBUG && helper === null) { + // Keyword helper did not exist, which means that we're attempting to use a + // value of some kind that is not in scope + throw new Error(`Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${meta.upvars[expr[1]]}`); + } + + return constants.helper(helper, name); +} + +class Compilers { + constructor() { + this.names = {}; + this.funcs = []; + } + + add(name, func) { + this.names[name] = this.funcs.push(func) - 1; + } + + compile(op, sexp) { + let name = sexp[0]; + let index = this.names[name]; + let func = this.funcs[index]; + func(op, sexp); + } + +} + +const EXPRESSIONS = new Compilers(); +EXPRESSIONS.add(29 +/* Concat */ +, (op, [, parts]) => { + for (let part of parts) { + expr(op, part); + } + + op(27 + /* Concat */ + , parts.length); +}); +EXPRESSIONS.add(28 +/* Call */ +, (op, [, expression, positional, named]) => { + if (isGetFreeHelper(expression)) { + op(1005 + /* ResolveHelper */ + , expression, handle => { + Call(op, handle, positional, named); + }); + } else { + expr(op, expression); + CallDynamic(op, positional, named); + } +}); +EXPRESSIONS.add(50 +/* Curry */ +, (op, [, expr$$1, type, positional, named]) => { + Curry(op, type, expr$$1, positional, named); +}); +EXPRESSIONS.add(30 +/* GetSymbol */ +, (op, [, sym, path]) => { + op(21 + /* GetVariable */ + , sym); + withPath(op, path); +}); +EXPRESSIONS.add(32 +/* GetTemplateSymbol */ +, (op, [, sym, path]) => { + op(1011 + /* ResolveTemplateLocal */ + , sym, handle => { + op(29 + /* ConstantReference */ + , handle); + withPath(op, path); + }); +}); +EXPRESSIONS.add(31 +/* GetStrictFree */ +, (op, [, sym, _path]) => { + op(1009 + /* ResolveFree */ + , sym, _handle => {// TODO: Implement in strict mode + }); +}); +EXPRESSIONS.add(33 +/* GetFreeAsFallback */ +, (op, [, freeVar, path]) => { + op(1010 + /* ResolveLocal */ + , freeVar, (name, moduleName) => { + if (DEBUG) { + let propertyPath = path ? [name, ...path].join('.') : name; + deprecate(`The \`${propertyPath}\` property path was used in the \`${moduleName}\` template without using \`this\`. This fallback behavior has been deprecated, all properties must be looked up on \`this\` when used in the template: {{this.${propertyPath}}}`, false, { + id: 'this-property-fallback' + }); + } + + op(21 + /* GetVariable */ + , 0); + op(22 + /* GetProperty */ + , name); + }); + withPath(op, path); +}); +EXPRESSIONS.add(34 +/* GetFreeAsComponentOrHelperHeadOrThisFallback */ +, () => { + // TODO: The logic for this opcode currently exists in STATEMENTS.Append, since + // we want different wrapping logic depending on if we are invoking a component, + // helper, or {{this}} fallback. Eventually we fix the opcodes so that we can + // traverse the subexpression tree like normal in this location. + throw new Error('unimplemented opcode'); +}); +EXPRESSIONS.add(36 +/* GetFreeAsHelperHeadOrThisFallback */ +, (op, expr$$1) => { + //
+ op(1010 + /* ResolveLocal */ + , expr$$1[1], _name => { + op(1006 + /* ResolveOptionalHelper */ + , expr$$1, { + ifHelper: handle => { + Call(op, handle, null, null); + }, + ifFallback: (name, moduleName) => { + deprecate(`The \`${name}\` property was used in the \`${moduleName}\` template without using \`this\`. This fallback behavior has been deprecated, all properties must be looked up on \`this\` when used in the template: {{this.${name}}}`, false, { + id: 'this-property-fallback' + }); + op(21 + /* GetVariable */ + , 0); + op(22 + /* GetProperty */ + , name); + } + }); + }); +}); +EXPRESSIONS.add(99 +/* GetFreeAsDeprecatedHelperHeadOrThisFallback */ +, (op, expr$$1) => { + // + op(1010 + /* ResolveLocal */ + , expr$$1[1], _name => { + op(1006 + /* ResolveOptionalHelper */ + , expr$$1, { + ifHelper: (handle, name, moduleName) => { + assert(expr$$1[2] && expr$$1[2].length === 1, '[BUG] Missing argument name'); + let arg = expr$$1[2][0]; + deprecate(`The \`${name}\` helper was used in the \`${moduleName}\` template as \`${arg}={{${name}}}\`. ` + `This is ambigious between wanting the \`${arg}\` argument to be the \`${name}\` helper itself, ` + `or the result of invoking the \`${name}\` helper (current behavior). ` + `This implicit invocation behavior has been deprecated.\n\n` + `Instead, please explicitly invoke the helper with parenthesis, i.e. \`${arg}={{(${name})}}\`.\n\n` + `Note: the parenthesis are only required in this exact scenario where an ambiguity is present – where ` + `\`${name}\` referes to a global helper (as opposed to a local variable), AND ` + `the \`${name}\` helper invocation does not take any arguments, AND ` + `this occurs in a named argument position of a component invocation.\n\n` + `We expect this combination to be quite rare, as most helpers require at least one argument. ` + `There is no need to refactor helper invocations in cases where this deprecation was not triggered.`, false, { + id: 'argument-less-helper-paren-less-invocation' + }); + Call(op, handle, null, null); + }, + ifFallback: (name, moduleName) => { + deprecate(`The \`${name}\` property was used in the \`${moduleName}\` template without using \`this\`. This fallback behavior has been deprecated, all properties must be looked up on \`this\` when used in the template: {{this.${name}}}`, false, { + id: 'this-property-fallback' + }); + op(21 + /* GetVariable */ + , 0); + op(22 + /* GetProperty */ + , name); + } + }); + }); +}); + +function withPath(op, path) { + if (path === undefined || path.length === 0) return; + + for (let i = 0; i < path.length; i++) { + op(22 + /* GetProperty */ + , path[i]); + } +} + +EXPRESSIONS.add(27 +/* Undefined */ +, op => PushPrimitiveReference(op, undefined)); +EXPRESSIONS.add(48 +/* HasBlock */ +, (op, [, block]) => { + expr(op, block); + op(25 + /* HasBlock */ + ); +}); +EXPRESSIONS.add(49 +/* HasBlockParams */ +, (op, [, block]) => { + expr(op, block); + op(24 + /* SpreadBlock */ + ); + op(61 + /* CompileBlock */ + ); + op(26 + /* HasBlockParams */ + ); +}); +EXPRESSIONS.add(52 +/* IfInline */ +, (op, [, condition, truthy, falsy]) => { + // Push in reverse order + expr(op, falsy); + expr(op, truthy); + expr(op, condition); + op(109 + /* IfInline */ + ); +}); +EXPRESSIONS.add(51 +/* Not */ +, (op, [, value]) => { + expr(op, value); + op(110 + /* Not */ + ); +}); +EXPRESSIONS.add(53 +/* GetDynamicVar */ +, (op, [, expression]) => { + expr(op, expression); + op(111 + /* GetDynamicVar */ + ); +}); +EXPRESSIONS.add(54 +/* Log */ +, (op, [, positional]) => { + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, null, false); + op(112 + /* Log */ + ); + op(1 + /* PopFrame */ + ); + op(36 + /* Fetch */ + , $v0); +}); + +function expr(op, expression) { + if (Array.isArray(expression)) { + EXPRESSIONS.compile(op, expression); + } else { + PushPrimitive(op, expression); + op(31 + /* PrimitiveReference */ + ); + } +} + +/** + * Compile arguments, pushing an Arguments object onto the stack. + * + * @param args.params + * @param args.hash + * @param args.blocks + * @param args.atNames + */ + +function CompileArgs(op, positional, named, blocks, atNames) { + let blockNames = blocks.names; + + for (let i = 0; i < blockNames.length; i++) { + PushYieldableBlock(op, blocks.get(blockNames[i])); + } + + let count = CompilePositional(op, positional); + let flags = count << 4; + if (atNames) flags |= 0b1000; + + if (blocks) { + flags |= 0b111; + } + + let names = EMPTY_ARRAY; + + if (named) { + names = named[0]; + let val = named[1]; + + for (let i = 0; i < val.length; i++) { + expr(op, val[i]); + } + } + + op(82 + /* PushArgs */ + , names, blockNames, flags); +} +function SimpleArgs(op, positional, named, atNames) { + if (positional === null && named === null) { + op(83 + /* PushEmptyArgs */ + ); + return; + } + + let count = CompilePositional(op, positional); + let flags = count << 4; + if (atNames) flags |= 0b1000; + let names = EMPTY_STRING_ARRAY; + + if (named) { + names = named[0]; + let val = named[1]; + + for (let i = 0; i < val.length; i++) { + expr(op, val[i]); + } + } + + op(82 + /* PushArgs */ + , names, EMPTY_STRING_ARRAY, flags); +} +/** + * Compile an optional list of positional arguments, which pushes each argument + * onto the stack and returns the number of parameters compiled + * + * @param positional an optional list of positional arguments + */ + +function CompilePositional(op, positional) { + if (positional === null) return 0; + + for (let i = 0; i < positional.length; i++) { + expr(op, positional[i]); + } + + return positional.length; +} +function meta(layout) { + var _a, _b; + + let [, symbols,, upvars] = layout.block; + return { + asPartial: layout.asPartial || false, + evalSymbols: evalSymbols(layout), + upvars: upvars, + scopeValues: (_b = (_a = layout.scope) === null || _a === void 0 ? void 0 : _a.call(layout)) !== null && _b !== void 0 ? _b : null, + isStrictMode: layout.isStrictMode, + moduleName: layout.moduleName, + owner: layout.owner, + size: symbols.length + }; +} +function evalSymbols(layout) { + let { + block + } = layout; + let [, symbols, hasEval] = block; + return hasEval ? symbols : null; +} + +/** + * Push a reference onto the stack corresponding to a statically known primitive + * @param value A JavaScript primitive (undefined, null, boolean, number or string) + */ + +function PushPrimitiveReference(op, value) { + PushPrimitive(op, value); + op(31 + /* PrimitiveReference */ + ); +} +/** + * Push an encoded representation of a JavaScript primitive on the stack + * + * @param value A JavaScript primitive (undefined, null, boolean, number or string) + */ + +function PushPrimitive(op, primitive) { + let p = primitive; + + if (typeof p === 'number') { + p = isSmallInt(p) ? encodeImmediate(p) : nonSmallIntOperand(p); + } + + op(30 + /* Primitive */ + , p); +} +/** + * Invoke a foreign function (a "helper") based on a statically known handle + * + * @param op The op creation function + * @param handle A handle + * @param positional An optional list of expressions to compile + * @param named An optional list of named arguments (name + expression) to compile + */ + +function Call(op, handle, positional, named) { + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, named, false); + op(16 + /* Helper */ + , handle); + op(1 + /* PopFrame */ + ); + op(36 + /* Fetch */ + , $v0); +} +/** + * Invoke a foreign function (a "helper") based on a dynamically loaded definition + * + * @param op The op creation function + * @param positional An optional list of expressions to compile + * @param named An optional list of named arguments (name + expression) to compile + */ + +function CallDynamic(op, positional, named, append) { + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, named, false); + op(33 + /* Dup */ + , $fp, 1); + op(107 + /* DynamicHelper */ + ); + + if (append) { + op(36 + /* Fetch */ + , $v0); + append(); + op(1 + /* PopFrame */ + ); + op(34 + /* Pop */ + , 1); + } else { + op(1 + /* PopFrame */ + ); + op(34 + /* Pop */ + , 1); + op(36 + /* Fetch */ + , $v0); + } +} +/** + * Evaluate statements in the context of new dynamic scope entries. Move entries from the + * stack into named entries in the dynamic scope, then evaluate the statements, then pop + * the dynamic scope + * + * @param names a list of dynamic scope names + * @param block a function that returns a list of statements to evaluate + */ + +function DynamicScope(op, names, block) { + op(59 + /* PushDynamicScope */ + ); + op(58 + /* BindDynamicScope */ + , names); + block(); + op(60 + /* PopDynamicScope */ + ); +} +function Curry(op, type, definition, positional, named) { + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, named, false); + op(86 + /* CaptureArgs */ + ); + expr(op, definition); + op(77 + /* Curry */ + , type, isStrictMode()); + op(1 + /* PopFrame */ + ); + op(36 + /* Fetch */ + , $v0); +} + +/** + * Yield to a block located at a particular symbol location. + * + * @param to the symbol containing the block to yield to + * @param params optional block parameters to yield to the block + */ + +function YieldBlock(op, to, positional) { + SimpleArgs(op, positional, null, true); + op(23 + /* GetBlock */ + , to); + op(24 + /* SpreadBlock */ + ); + op(61 + /* CompileBlock */ + ); + op(64 + /* InvokeYield */ + ); + op(40 + /* PopScope */ + ); + op(1 + /* PopFrame */ + ); +} +/** + * Push an (optional) yieldable block onto the stack. The yieldable block must be known + * statically at compile time. + * + * @param block An optional Compilable block + */ + +function PushYieldableBlock(op, block) { + PushSymbolTable(op, block && block[1]); + op(62 + /* PushBlockScope */ + ); + PushCompilable(op, block); +} +/** + * Invoke a block that is known statically at compile time. + * + * @param block a Compilable block + */ + +function InvokeStaticBlock(op, block) { + op(0 + /* PushFrame */ + ); + PushCompilable(op, block); + op(61 + /* CompileBlock */ + ); + op(2 + /* InvokeVirtual */ + ); + op(1 + /* PopFrame */ + ); +} +/** + * Invoke a static block, preserving some number of stack entries for use in + * updating. + * + * @param block A compilable block + * @param callerCount A number of stack entries to preserve + */ + +function InvokeStaticBlockWithStack(op, block, callerCount) { + let parameters = block[1]; + let calleeCount = parameters.length; + let count = Math.min(callerCount, calleeCount); + + if (count === 0) { + InvokeStaticBlock(op, block); + return; + } + + op(0 + /* PushFrame */ + ); + + if (count) { + op(39 + /* ChildScope */ + ); + + for (let i = 0; i < count; i++) { + op(33 + /* Dup */ + , $fp, callerCount - i); + op(19 + /* SetVariable */ + , parameters[i]); + } + } + + PushCompilable(op, block); + op(61 + /* CompileBlock */ + ); + op(2 + /* InvokeVirtual */ + ); + + if (count) { + op(40 + /* PopScope */ + ); + } + + op(1 + /* PopFrame */ + ); +} +function PushSymbolTable(op, parameters) { + if (parameters !== null) { + op(63 + /* PushSymbolTable */ + , symbolTableOperand({ + parameters + })); + } else { + PushPrimitive(op, null); + } +} +function PushCompilable(op, _block) { + if (_block === null) { + PushPrimitive(op, null); + } else { + op(28 + /* Constant */ + , blockOperand(_block)); + } +} + +function SwitchCases(op, bootstrap, callback) { + // Setup the switch DSL + let clauses = []; + let count = 0; + + function when(match, callback) { + clauses.push({ + match, + callback, + label: `CLAUSE${count++}` + }); + } // Call the callback + + + callback(when); // Emit the opcodes for the switch + + op(69 + /* Enter */ + , 1); + bootstrap(); + op(1001 + /* StartLabels */ + ); // First, emit the jump opcodes. We don't need a jump for the last + // opcode, since it bleeds directly into its clause. + + for (let clause of clauses.slice(0, -1)) { + op(67 + /* JumpEq */ + , labelOperand(clause.label), clause.match); + } // Enumerate the clauses in reverse order. Earlier matches will + // require fewer checks. + + + for (let i = clauses.length - 1; i >= 0; i--) { + let clause = clauses[i]; + op(1000 + /* Label */ + , clause.label); + op(34 + /* Pop */ + , 1); + clause.callback(); // The first match is special: it is placed directly before the END + // label, so no additional jump is needed at the end of it. + + if (i !== 0) { + op(4 + /* Jump */ + , labelOperand('END')); + } + } + + op(1000 + /* Label */ + , 'END'); + op(1002 + /* StopLabels */ + ); + op(70 + /* Exit */ + ); +} +/** + * A convenience for pushing some arguments on the stack and + * running some code if the code needs to be re-executed during + * updating execution if some of the arguments have changed. + * + * # Initial Execution + * + * The `args` function should push zero or more arguments onto + * the stack and return the number of arguments pushed. + * + * The `body` function provides the instructions to execute both + * during initial execution and during updating execution. + * + * Internally, this function starts by pushing a new frame, so + * that the body can return and sets the return point ($ra) to + * the ENDINITIAL label. + * + * It then executes the `args` function, which adds instructions + * responsible for pushing the arguments for the block to the + * stack. These arguments will be restored to the stack before + * updating execution. + * + * Next, it adds the Enter opcode, which marks the current position + * in the DOM, and remembers the current $pc (the next instruction) + * as the first instruction to execute during updating execution. + * + * Next, it runs `body`, which adds the opcodes that should + * execute both during initial execution and during updating execution. + * If the `body` wishes to finish early, it should Jump to the + * `FINALLY` label. + * + * Next, it adds the FINALLY label, followed by: + * + * - the Exit opcode, which finalizes the marked DOM started by the + * Enter opcode. + * - the Return opcode, which returns to the current return point + * ($ra). + * + * Finally, it adds the ENDINITIAL label followed by the PopFrame + * instruction, which restores $fp, $sp and $ra. + * + * # Updating Execution + * + * Updating execution for this `replayable` occurs if the `body` added an + * assertion, via one of the `JumpIf`, `JumpUnless` or `AssertSame` opcodes. + * + * If, during updating executon, the assertion fails, the initial VM is + * restored, and the stored arguments are pushed onto the stack. The DOM + * between the starting and ending markers is cleared, and the VM's cursor + * is set to the area just cleared. + * + * The return point ($ra) is set to -1, the exit instruction. + * + * Finally, the $pc is set to to the instruction saved off by the + * Enter opcode during initial execution, and execution proceeds as + * usual. + * + * The only difference is that when a `Return` instruction is + * encountered, the program jumps to -1 rather than the END label, + * and the PopFrame opcode is not needed. + */ + +function Replayable(op, args, body) { + // Start a new label frame, to give END and RETURN + // a unique meaning. + op(1001 + /* StartLabels */ + ); + op(0 + /* PushFrame */ + ); // If the body invokes a block, its return will return to + // END. Otherwise, the return in RETURN will return to END. + + op(6 + /* ReturnTo */ + , labelOperand('ENDINITIAL')); // Push the arguments onto the stack. The args() function + // tells us how many stack elements to retain for re-execution + // when updating. + + let count = args(); // Start a new updating closure, remembering `count` elements + // from the stack. Everything after this point, and before END, + // will execute both initially and to update the block. + // + // The enter and exit opcodes also track the area of the DOM + // associated with this block. If an assertion inside the block + // fails (for example, the test value changes from true to false + // in an #if), the DOM is cleared and the program is re-executed, + // restoring `count` elements to the stack and executing the + // instructions between the enter and exit. + + op(69 + /* Enter */ + , count); // Evaluate the body of the block. The body of the block may + // return, which will jump execution to END during initial + // execution, and exit the updating routine. + + body(); // All execution paths in the body should run the FINALLY once + // they are done. It is executed both during initial execution + // and during updating execution. + + op(1000 + /* Label */ + , 'FINALLY'); // Finalize the DOM. + + op(70 + /* Exit */ + ); // In initial execution, this is a noop: it returns to the + // immediately following opcode. In updating execution, this + // exits the updating routine. + + op(5 + /* Return */ + ); // Cleanup code for the block. Runs on initial execution + // but not on updating. + + op(1000 + /* Label */ + , 'ENDINITIAL'); + op(1 + /* PopFrame */ + ); + op(1002 + /* StopLabels */ + ); +} +/** + * A specialized version of the `replayable` convenience that allows the + * caller to provide different code based upon whether the item at + * the top of the stack is true or false. + * + * As in `replayable`, the `ifTrue` and `ifFalse` code can invoke `return`. + * + * During the initial execution, a `return` will continue execution + * in the cleanup code, which finalizes the current DOM block and pops + * the current frame. + * + * During the updating execution, a `return` will exit the updating + * routine, as it can reuse the DOM block and is always only a single + * frame deep. + */ + +function ReplayableIf(op, args, ifTrue, ifFalse) { + return Replayable(op, args, () => { + // If the conditional is false, jump to the ELSE label. + op(66 + /* JumpUnless */ + , labelOperand('ELSE')); // Otherwise, execute the code associated with the true branch. + + ifTrue(); // We're done, so return. In the initial execution, this runs + // the cleanup code. In the updating VM, it exits the updating + // routine. + + op(4 + /* Jump */ + , labelOperand('FINALLY')); + op(1000 + /* Label */ + , 'ELSE'); // If the conditional is false, and code associatied ith the + // false branch was provided, execute it. If there was no code + // associated with the false branch, jumping to the else statement + // has no other behavior. + + if (ifFalse !== undefined) { + ifFalse(); + } + }); +} + +const ATTRS_BLOCK = '&attrs'; +function InvokeComponent(op, component, _elementBlock, positional, named, _blocks) { + let { + compilable, + capabilities, + handle + } = component; + let elementBlock = _elementBlock ? [_elementBlock, []] : null; + let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks; + + if (compilable) { + op(78 + /* PushComponentDefinition */ + , handle); + InvokeStaticComponent(op, { + capabilities: capabilities, + layout: compilable, + elementBlock, + positional, + named, + blocks + }); + } else { + op(78 + /* PushComponentDefinition */ + , handle); + InvokeNonStaticComponent(op, { + capabilities: capabilities, + elementBlock, + positional, + named, + atNames: true, + blocks + }); + } +} +function InvokeDynamicComponent(op, definition, _elementBlock, positional, named, _blocks, atNames, curried) { + let elementBlock = _elementBlock ? [_elementBlock, []] : null; + let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks; + Replayable(op, () => { + expr(op, definition); + op(33 + /* Dup */ + , $sp, 0); + return 2; + }, () => { + op(66 + /* JumpUnless */ + , labelOperand('ELSE')); + + if (curried) { + op(81 + /* ResolveCurriedComponent */ + ); + } else { + op(80 + /* ResolveDynamicComponent */ + , isStrictMode()); + } + + op(79 + /* PushDynamicComponentInstance */ + ); + InvokeNonStaticComponent(op, { + capabilities: true, + elementBlock, + positional, + named, + atNames, + blocks + }); + op(1000 + /* Label */ + , 'ELSE'); + }); +} + +function InvokeStaticComponent(op, { + capabilities, + layout, + elementBlock, + positional, + named, + blocks +}) { + let { + symbolTable + } = layout; + let bailOut = symbolTable.hasEval || hasCapability(capabilities, 4 + /* PrepareArgs */ + ); + + if (bailOut) { + InvokeNonStaticComponent(op, { + capabilities, + elementBlock, + positional, + named, + atNames: true, + blocks, + layout + }); + return; + } + + op(36 + /* Fetch */ + , $s0); + op(33 + /* Dup */ + , $sp, 1); + op(35 + /* Load */ + , $s0); + op(0 + /* PushFrame */ + ); // Setup arguments + + let { + symbols + } = symbolTable; // As we push values onto the stack, we store the symbols associated with them + // so that we can set them on the scope later on with SetVariable and SetBlock + + let blockSymbols = []; + let argSymbols = []; + let argNames = []; // First we push the blocks onto the stack + + let blockNames = blocks.names; // Starting with the attrs block, if it exists and is referenced in the component + + if (elementBlock !== null) { + let symbol = symbols.indexOf(ATTRS_BLOCK); + + if (symbol !== -1) { + PushYieldableBlock(op, elementBlock); + blockSymbols.push(symbol); + } + } // Followed by the other blocks, if they exist and are referenced in the component. + // Also store the index of the associated symbol. + + + for (let i = 0; i < blockNames.length; i++) { + let name = blockNames[i]; + let symbol = symbols.indexOf(`&${name}`); + + if (symbol !== -1) { + PushYieldableBlock(op, blocks.get(name)); + blockSymbols.push(symbol); + } + } // Next up we have arguments. If the component has the `createArgs` capability, + // then it wants access to the arguments in JavaScript. We can't know whether + // or not an argument is used, so we have to give access to all of them. + + + if (hasCapability(capabilities, 8 + /* CreateArgs */ + )) { + // First we push positional arguments + let count = CompilePositional(op, positional); // setup the flags with the count of positionals, and to indicate that atNames + // are used + + let flags = count << 4; + flags |= 0b1000; + let names = EMPTY_STRING_ARRAY; // Next, if named args exist, push them all. If they have an associated symbol + // in the invoked component (e.g. they are used within its template), we push + // that symbol. If not, we still push the expression as it may be used, and + // we store the symbol as -1 (this is used later). + + if (named !== null) { + names = named[0]; + let val = named[1]; + + for (let i = 0; i < val.length; i++) { + let symbol = symbols.indexOf(names[i]); + expr(op, val[i]); + argSymbols.push(symbol); + } + } // Finally, push the VM arguments themselves. These args won't need access + // to blocks (they aren't accessible from userland anyways), so we push an + // empty array instead of the actual block names. + + + op(82 + /* PushArgs */ + , names, EMPTY_STRING_ARRAY, flags); // And push an extra pop operation to remove the args before we begin setting + // variables on the local context + + argSymbols.push(-1); + } else if (named !== null) { + // If the component does not have the `createArgs` capability, then the only + // expressions we need to push onto the stack are those that are actually + // referenced in the template of the invoked component (e.g. have symbols). + let names = named[0]; + let val = named[1]; + + for (let i = 0; i < val.length; i++) { + let name = names[i]; + let symbol = symbols.indexOf(name); + + if (symbol !== -1) { + expr(op, val[i]); + argSymbols.push(symbol); + argNames.push(name); + } + } + } + + op(97 + /* BeginComponentTransaction */ + , $s0); + + if (hasCapability(capabilities, 64 + /* DynamicScope */ + )) { + op(59 + /* PushDynamicScope */ + ); + } + + if (hasCapability(capabilities, 512 + /* CreateInstance */ + )) { + op(87 + /* CreateComponent */ + , blocks.has('default') | 0, $s0); + } + + op(88 + /* RegisterComponentDestructor */ + , $s0); + + if (hasCapability(capabilities, 8 + /* CreateArgs */ + )) { + op(90 + /* GetComponentSelf */ + , $s0); + } else { + op(90 + /* GetComponentSelf */ + , $s0, argNames); + } // Setup the new root scope for the component + + + op(37 + /* RootScope */ + , symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0); // Pop the self reference off the stack and set it to the symbol for `this` + // in the new scope. This is why all subsequent symbols are increased by one. + + op(19 + /* SetVariable */ + , 0); // Going in reverse, now we pop the args/blocks off the stack, starting with + // arguments, and assign them to their symbols in the new scope. + + for (let i = argSymbols.length - 1; i >= 0; i--) { + let symbol = argSymbols[i]; + + if (symbol === -1) { + // The expression was not bound to a local symbol, it was only pushed to be + // used with VM args in the javascript side + op(34 + /* Pop */ + , 1); + } else { + op(19 + /* SetVariable */ + , symbol + 1); + } + } // if any positional params exist, pop them off the stack as well + + + if (positional !== null) { + op(34 + /* Pop */ + , positional.length); + } // Finish up by popping off and assigning blocks + + + for (let i = blockSymbols.length - 1; i >= 0; i--) { + let symbol = blockSymbols[i]; + op(20 + /* SetBlock */ + , symbol + 1); + } + + op(28 + /* Constant */ + , layoutOperand(layout)); + op(61 + /* CompileBlock */ + ); + op(2 + /* InvokeVirtual */ + ); + op(100 + /* DidRenderLayout */ + , $s0); + op(1 + /* PopFrame */ + ); + op(40 + /* PopScope */ + ); + + if (hasCapability(capabilities, 64 + /* DynamicScope */ + )) { + op(60 + /* PopDynamicScope */ + ); + } + + op(98 + /* CommitComponentTransaction */ + ); + op(35 + /* Load */ + , $s0); +} + +function InvokeNonStaticComponent(op, { + capabilities, + elementBlock, + positional, + named, + atNames, + blocks: namedBlocks$$1, + layout +}) { + let bindableBlocks = !!namedBlocks$$1; + let bindableAtNames = capabilities === true || hasCapability(capabilities, 4 + /* PrepareArgs */ + ) || !!(named && named[0].length !== 0); + let blocks = namedBlocks$$1.with('attrs', elementBlock); + op(36 + /* Fetch */ + , $s0); + op(33 + /* Dup */ + , $sp, 1); + op(35 + /* Load */ + , $s0); + op(0 + /* PushFrame */ + ); + CompileArgs(op, positional, named, blocks, atNames); + op(85 + /* PrepareArgs */ + , $s0); + invokePreparedComponent(op, blocks.has('default'), bindableBlocks, bindableAtNames, () => { + if (layout) { + op(63 + /* PushSymbolTable */ + , symbolTableOperand(layout.symbolTable)); + op(28 + /* Constant */ + , layoutOperand(layout)); + op(61 + /* CompileBlock */ + ); + } else { + op(92 + /* GetComponentLayout */ + , $s0); + } + + op(95 + /* PopulateLayout */ + , $s0); + }); + op(35 + /* Load */ + , $s0); +} +function WrappedComponent(op, layout, attrsBlockNumber) { + op(1001 + /* StartLabels */ + ); + WithSavedRegister(op, $s1, () => { + op(91 + /* GetComponentTagName */ + , $s0); + op(31 + /* PrimitiveReference */ + ); + op(33 + /* Dup */ + , $sp, 0); + }); + op(66 + /* JumpUnless */ + , labelOperand('BODY')); + op(36 + /* Fetch */ + , $s1); + op(89 + /* PutComponentOperations */ + ); + op(49 + /* OpenDynamicElement */ + ); + op(99 + /* DidCreateElement */ + , $s0); + YieldBlock(op, attrsBlockNumber, null); + op(54 + /* FlushElement */ + ); + op(1000 + /* Label */ + , 'BODY'); + InvokeStaticBlock(op, [layout.block[0], []]); + op(36 + /* Fetch */ + , $s1); + op(66 + /* JumpUnless */ + , labelOperand('END')); + op(55 + /* CloseElement */ + ); + op(1000 + /* Label */ + , 'END'); + op(35 + /* Load */ + , $s1); + op(1002 + /* StopLabels */ + ); +} +function invokePreparedComponent(op, hasBlock, bindableBlocks, bindableAtNames, populateLayout = null) { + op(97 + /* BeginComponentTransaction */ + , $s0); + op(59 + /* PushDynamicScope */ + ); + op(87 + /* CreateComponent */ + , hasBlock | 0, $s0); // this has to run after createComponent to allow + // for late-bound layouts, but a caller is free + // to populate the layout earlier if it wants to + // and do nothing here. + + if (populateLayout) { + populateLayout(); + } + + op(88 + /* RegisterComponentDestructor */ + , $s0); + op(90 + /* GetComponentSelf */ + , $s0); + op(38 + /* VirtualRootScope */ + , $s0); + op(19 + /* SetVariable */ + , 0); + op(94 + /* SetupForEval */ + , $s0); + if (bindableAtNames) op(17 + /* SetNamedVariables */ + , $s0); + if (bindableBlocks) op(18 + /* SetBlocks */ + , $s0); + op(34 + /* Pop */ + , 1); + op(96 + /* InvokeComponentLayout */ + , $s0); + op(100 + /* DidRenderLayout */ + , $s0); + op(1 + /* PopFrame */ + ); + op(40 + /* PopScope */ + ); + op(60 + /* PopDynamicScope */ + ); + op(98 + /* CommitComponentTransaction */ + ); +} +function InvokeBareComponent(op) { + op(36 + /* Fetch */ + , $s0); + op(33 + /* Dup */ + , $sp, 1); + op(35 + /* Load */ + , $s0); + op(0 + /* PushFrame */ + ); + op(83 + /* PushEmptyArgs */ + ); + op(85 + /* PrepareArgs */ + , $s0); + invokePreparedComponent(op, false, false, true, () => { + op(92 + /* GetComponentLayout */ + , $s0); + op(95 + /* PopulateLayout */ + , $s0); + }); + op(35 + /* Load */ + , $s0); +} +function WithSavedRegister(op, register, block) { + op(36 + /* Fetch */ + , register); + block(); + op(35 + /* Load */ + , register); +} + +class StdLib { + constructor(main, trustingGuardedAppend, cautiousGuardedAppend, trustingNonDynamicAppend, cautiousNonDynamicAppend) { + this.main = main; + this.trustingGuardedAppend = trustingGuardedAppend; + this.cautiousGuardedAppend = cautiousGuardedAppend; + this.trustingNonDynamicAppend = trustingNonDynamicAppend; + this.cautiousNonDynamicAppend = cautiousNonDynamicAppend; + } + + get 'trusting-append'() { + return this.trustingGuardedAppend; + } + + get 'cautious-append'() { + return this.cautiousGuardedAppend; + } + + get 'trusting-non-dynamic-append'() { + return this.trustingNonDynamicAppend; + } + + get 'cautious-non-dynamic-append'() { + return this.cautiousNonDynamicAppend; + } + + getAppend(trusting) { + return trusting ? this.trustingGuardedAppend : this.cautiousGuardedAppend; + } + +} + +function programCompilationContext(artifacts, resolver) { + return new CompileTimeCompilationContextImpl(artifacts, resolver); +} +function templateCompilationContext(program, meta) { + let encoder = new EncoderImpl(program.heap, meta, program.stdlib); + return { + program, + encoder, + meta + }; +} + +let debugCompiler; + +const STATEMENTS = new Compilers(); +const INFLATE_ATTR_TABLE = ['class', 'id', 'value', 'name', 'type', 'style', 'href']; +const INFLATE_TAG_TABLE = ['div', 'span', 'p', 'a']; +function inflateTagName(tagName) { + return typeof tagName === 'string' ? tagName : INFLATE_TAG_TABLE[tagName]; +} +function inflateAttrName(attrName) { + return typeof attrName === 'string' ? attrName : INFLATE_ATTR_TABLE[attrName]; +} +STATEMENTS.add(3 +/* Comment */ +, (op, sexp) => op(42 +/* Comment */ +, sexp[1])); +STATEMENTS.add(13 +/* CloseElement */ +, op => op(55 +/* CloseElement */ +)); +STATEMENTS.add(12 +/* FlushElement */ +, op => op(54 +/* FlushElement */ +)); +STATEMENTS.add(4 +/* Modifier */ +, (op, [, expression, positional, named]) => { + if (isGetFreeModifier(expression)) { + op(1003 + /* ResolveModifier */ + , expression, handle => { + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, named, false); + op(57 + /* Modifier */ + , handle); + op(1 + /* PopFrame */ + ); + }); + } else { + expr(op, expression); + op(0 + /* PushFrame */ + ); + SimpleArgs(op, positional, named, false); + op(33 + /* Dup */ + , $fp, 1); + op(108 + /* DynamicModifier */ + ); + op(1 + /* PopFrame */ + ); + } +}); +STATEMENTS.add(14 +/* StaticAttr */ +, (op, [, name, value, namespace]) => { + op(51 + /* StaticAttr */ + , inflateAttrName(name), value, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(24 +/* StaticComponentAttr */ +, (op, [, name, value, namespace]) => { + op(105 + /* StaticComponentAttr */ + , inflateAttrName(name), value, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(15 +/* DynamicAttr */ +, (op, [, name, value, namespace]) => { + expr(op, value); + op(52 + /* DynamicAttr */ + , inflateAttrName(name), false, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(22 +/* TrustingDynamicAttr */ +, (op, [, name, value, namespace]) => { + expr(op, value); + op(52 + /* DynamicAttr */ + , inflateAttrName(name), true, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(16 +/* ComponentAttr */ +, (op, [, name, value, namespace]) => { + expr(op, value); + op(53 + /* ComponentAttr */ + , inflateAttrName(name), false, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(23 +/* TrustingComponentAttr */ +, (op, [, name, value, namespace]) => { + expr(op, value); + op(53 + /* ComponentAttr */ + , inflateAttrName(name), true, namespace !== null && namespace !== void 0 ? namespace : null); +}); +STATEMENTS.add(10 +/* OpenElement */ +, (op, [, tag]) => { + op(48 + /* OpenElement */ + , inflateTagName(tag)); +}); +STATEMENTS.add(11 +/* OpenElementWithSplat */ +, (op, [, tag]) => { + op(89 + /* PutComponentOperations */ + ); + op(48 + /* OpenElement */ + , inflateTagName(tag)); +}); +STATEMENTS.add(8 +/* Component */ +, (op, [, expr$$1, elementBlock, named, blocks]) => { + if (isGetFreeComponent(expr$$1)) { + op(1004 + /* ResolveComponent */ + , expr$$1, component => { + InvokeComponent(op, component, elementBlock, null, named, blocks); + }); + } else { + // otherwise, the component name was an expression, so resolve the expression + // and invoke it as a dynamic component + InvokeDynamicComponent(op, expr$$1, elementBlock, null, named, blocks, true, true); + } +}); +STATEMENTS.add(19 +/* Partial */ +, (op, [, name, evalInfo]) => { + ReplayableIf(op, () => { + expr(op, name); + op(33 + /* Dup */ + , $sp, 0); + return 2; + }, () => { + op(101 + /* InvokePartial */ + , evalSymbolsOperand(), evalInfo); + op(40 + /* PopScope */ + ); + op(1 + /* PopFrame */ + ); + }); +}); +STATEMENTS.add(18 +/* Yield */ +, (op, [, to, params]) => YieldBlock(op, to, params)); +STATEMENTS.add(17 +/* AttrSplat */ +, (op, [, to]) => YieldBlock(op, to, null)); +STATEMENTS.add(26 +/* Debugger */ +, (op, [, evalInfo]) => op(103 +/* Debugger */ +, evalSymbolsOperand(), evalInfo)); +STATEMENTS.add(1 +/* Append */ +, (op, [, value]) => { + // Special case for static values + if (!Array.isArray(value)) { + op(41 + /* Text */ + , value === null || value === undefined ? '' : String(value)); + } else if (isGetFreeOptionalComponentOrHelper(value)) { + op(1008 + /* ResolveOptionalComponentOrHelper */ + , value, { + ifComponent(component) { + InvokeComponent(op, component, null, null, null, null); + }, + + ifHelper(handle) { + op(0 + /* PushFrame */ + ); + Call(op, handle, null, null); + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-non-dynamic-append')); + op(1 + /* PopFrame */ + ); + }, + + ifValue(handle) { + op(0 + /* PushFrame */ + ); + op(29 + /* ConstantReference */ + , handle); + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-non-dynamic-append')); + op(1 + /* PopFrame */ + ); + }, + + ifFallback(_name) { + op(0 + /* PushFrame */ + ); + op(1010 + /* ResolveLocal */ + , value[1], (name, moduleName) => { + deprecate(`The \`${name}\` property was used in the \`${moduleName}\` template without using \`this\`. This fallback behavior has been deprecated, all properties must be looked up on \`this\` when used in the template: {{this.${name}}}`, false, { + id: 'this-property-fallback' + }); + op(21 + /* GetVariable */ + , 0); + op(22 + /* GetProperty */ + , name); + }); + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-append')); + op(1 + /* PopFrame */ + ); + } + + }); + } else if (value[0] === 28 + /* Call */ + ) { + let [, expression, positional, named] = value; + + if (isGetFreeComponentOrHelper(expression)) { + op(1007 + /* ResolveComponentOrHelper */ + , expression, { + ifComponent(component) { + InvokeComponent(op, component, null, positional, hashToArgs(named), null); + }, + + ifHelper(handle) { + op(0 + /* PushFrame */ + ); + Call(op, handle, positional, named); + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-non-dynamic-append')); + op(1 + /* PopFrame */ + ); + } + + }); + } else { + SwitchCases(op, () => { + expr(op, expression); + op(106 + /* DynamicContentType */ + ); + }, when => { + when(0 + /* Component */ + , () => { + op(81 + /* ResolveCurriedComponent */ + ); + op(79 + /* PushDynamicComponentInstance */ + ); + InvokeNonStaticComponent(op, { + capabilities: true, + elementBlock: null, + positional, + named, + atNames: false, + blocks: namedBlocks(null) + }); + }); + when(1 + /* Helper */ + , () => { + CallDynamic(op, positional, named, () => { + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-non-dynamic-append')); + }); + }); + }); + } + } else { + op(0 + /* PushFrame */ + ); + expr(op, value); + op(3 + /* InvokeStatic */ + , stdlibOperand('cautious-append')); + op(1 + /* PopFrame */ + ); + } +}); +STATEMENTS.add(2 +/* TrustingAppend */ +, (op, [, value]) => { + if (!Array.isArray(value)) { + op(41 + /* Text */ + , value === null || value === undefined ? '' : String(value)); + } else { + op(0 + /* PushFrame */ + ); + expr(op, value); + op(3 + /* InvokeStatic */ + , stdlibOperand('trusting-append')); + op(1 + /* PopFrame */ + ); + } +}); +STATEMENTS.add(6 +/* Block */ +, (op, [, expr$$1, positional, named, blocks]) => { + if (isGetFreeComponent(expr$$1)) { + op(1004 + /* ResolveComponent */ + , expr$$1, component => { + InvokeComponent(op, component, null, positional, hashToArgs(named), blocks); + }); + } else { + InvokeDynamicComponent(op, expr$$1, null, positional, named, blocks, false, false); + } +}); +STATEMENTS.add(40 +/* InElement */ +, (op, [, block, guid, destination, insertBefore]) => { + ReplayableIf(op, () => { + expr(op, guid); + + if (insertBefore === undefined) { + PushPrimitiveReference(op, undefined); + } else { + expr(op, insertBefore); + } + + expr(op, destination); + op(33 + /* Dup */ + , $sp, 0); + return 4; + }, () => { + op(50 + /* PushRemoteElement */ + ); + InvokeStaticBlock(op, block); + op(56 + /* PopRemoteElement */ + ); + }); +}); +STATEMENTS.add(41 +/* If */ +, (op, [, condition, block, inverse]) => ReplayableIf(op, () => { + expr(op, condition); + op(71 + /* ToBoolean */ + ); + return 1; +}, () => { + InvokeStaticBlock(op, block); +}, inverse ? () => { + InvokeStaticBlock(op, inverse); +} : undefined)); +STATEMENTS.add(42 +/* Each */ +, (op, [, value, key, block, inverse]) => Replayable(op, () => { + if (key) { + expr(op, key); + } else { + PushPrimitiveReference(op, null); + } + + expr(op, value); + return 2; +}, () => { + op(72 + /* EnterList */ + , labelOperand('BODY'), labelOperand('ELSE')); + op(0 + /* PushFrame */ + ); + op(33 + /* Dup */ + , $fp, 1); + op(6 + /* ReturnTo */ + , labelOperand('ITER')); + op(1000 + /* Label */ + , 'ITER'); + op(74 + /* Iterate */ + , labelOperand('BREAK')); + op(1000 + /* Label */ + , 'BODY'); + InvokeStaticBlockWithStack(op, block, 2); + op(34 + /* Pop */ + , 2); + op(4 + /* Jump */ + , labelOperand('FINALLY')); + op(1000 + /* Label */ + , 'BREAK'); + op(1 + /* PopFrame */ + ); + op(73 + /* ExitList */ + ); + op(4 + /* Jump */ + , labelOperand('FINALLY')); + op(1000 + /* Label */ + , 'ELSE'); + + if (inverse) { + InvokeStaticBlock(op, inverse); + } +})); +STATEMENTS.add(43 +/* With */ +, (op, [, value, block, inverse]) => { + ReplayableIf(op, () => { + expr(op, value); + op(33 + /* Dup */ + , $sp, 0); + op(71 + /* ToBoolean */ + ); + return 2; + }, () => { + InvokeStaticBlockWithStack(op, block, 1); + }, () => { + if (inverse) { + InvokeStaticBlock(op, inverse); + } + }); +}); +STATEMENTS.add(44 +/* Let */ +, (op, [, positional, block]) => { + let count = CompilePositional(op, positional); + InvokeStaticBlockWithStack(op, block, count); +}); +STATEMENTS.add(45 +/* WithDynamicVars */ +, (op, [, named, block]) => { + if (named) { + let [names, expressions] = named; + CompilePositional(op, expressions); + DynamicScope(op, names, () => { + InvokeStaticBlock(op, block); + }); + } else { + InvokeStaticBlock(op, block); + } +}); +STATEMENTS.add(46 +/* InvokeComponent */ +, (op, [, expr$$1, positional, named, blocks]) => { + if (isGetFreeComponent(expr$$1)) { + op(1004 + /* ResolveComponent */ + , expr$$1, component => { + InvokeComponent(op, component, null, positional, hashToArgs(named), blocks); + }); + } else { + InvokeDynamicComponent(op, expr$$1, null, positional, named, blocks, false, false); + } +}); + +function hashToArgs(hash) { + if (hash === null) return null; + let names = hash[0].map(key => `@${key}`); + return [names, hash[1]]; +} + +const PLACEHOLDER_HANDLE = -1; + +class CompilableTemplateImpl { + constructor(statements, meta$$1, // Part of CompilableTemplate + symbolTable, // Used for debugging + moduleName = 'plain block') { + this.statements = statements; + this.meta = meta$$1; + this.symbolTable = symbolTable; + this.moduleName = moduleName; + this.compiled = null; + } // Part of CompilableTemplate + + + compile(context) { + return maybeCompile(this, context); + } + +} + +function compilable(layout, moduleName) { + let [statements, symbols, hasEval] = layout.block; + return new CompilableTemplateImpl(statements, meta(layout), { + symbols, + hasEval + }, moduleName); +} + +function maybeCompile(compilable, context) { + if (compilable.compiled !== null) return compilable.compiled; + compilable.compiled = PLACEHOLDER_HANDLE; + let { + statements, + meta: meta$$1 + } = compilable; + let result = compileStatements(statements, meta$$1, context); + compilable.compiled = result; + return result; +} + +function compileStatements(statements, meta$$1, syntaxContext) { + let sCompiler = STATEMENTS; + let context = templateCompilationContext(syntaxContext, meta$$1); + let { + encoder, + program: { + constants, + resolver + } + } = context; + + function pushOp(...op) { + encodeOp(encoder, constants, resolver, meta$$1, op); + } + + for (let i = 0; i < statements.length; i++) { + sCompiler.compile(pushOp, statements[i]); + } + + let handle = context.encoder.commit(meta$$1.size); + + return handle; +} +function compilableBlock(block, containing) { + return new CompilableTemplateImpl(block[0], containing, { + parameters: block[1] || EMPTY_ARRAY + }); +} + +class Labels { + constructor() { + this.labels = dict(); + this.targets = []; + } + + label(name, index) { + this.labels[name] = index; + } + + target(at, target) { + this.targets.push({ + at, + target + }); + } + + patch(heap) { + let { + targets, + labels + } = this; + + for (let i = 0; i < targets.length; i++) { + let { + at, + target + } = targets[i]; + let address = labels[target] - at; + heap.setbyaddr(at, address); + } + } + +} +function encodeOp(encoder, constants, resolver, meta, op) { + if (isBuilderOpcode(op[0])) { + let [type, ...operands] = op; + encoder.push(constants, type, ...operands); + } else { + switch (op[0]) { + case 1000 + /* Label */ + : + return encoder.label(op[1]); + + case 1001 + /* StartLabels */ + : + return encoder.startLabels(); + + case 1002 + /* StopLabels */ + : + return encoder.stopLabels(); + + case 1004 + /* ResolveComponent */ + : + return resolveComponent(resolver, constants, meta, op); + + case 1003 + /* ResolveModifier */ + : + return resolveModifier(resolver, constants, meta, op); + + case 1005 + /* ResolveHelper */ + : + return resolveHelper(resolver, constants, meta, op); + + case 1007 + /* ResolveComponentOrHelper */ + : + return resolveComponentOrHelper(resolver, constants, meta, op); + + case 1006 + /* ResolveOptionalHelper */ + : + return resolveOptionalHelper(resolver, constants, meta, op); + + case 1008 + /* ResolveOptionalComponentOrHelper */ + : + return resolveOptionalComponentOrHelper(resolver, constants, meta, op); + + case 1010 + /* ResolveLocal */ + : + let freeVar = op[1]; + let name = meta.upvars[freeVar]; + + if (meta.asPartial === true) { + encoder.push(constants, 102 + /* ResolveMaybeLocal */ + , name); + } else { + let then = op[2]; + then(name, meta.moduleName); + } + + break; + + case 1011 + /* ResolveTemplateLocal */ + : + let [, valueIndex, then] = op; + let value = meta.scopeValues[valueIndex]; + then(constants.value(value)); + break; + + case 1009 + /* ResolveFree */ + : + if (DEBUG) { + let [, upvarIndex] = op; + let freeName = meta.upvars[upvarIndex]; + throw new Error(`Attempted to resolve a value in a strict mode template, but that value was not in scope: ${freeName}`); + } + + break; + + default: + throw new Error(`Unexpected high level opcode ${op[0]}`); + } + } +} +class EncoderImpl { + constructor(heap, meta, stdlib) { + this.heap = heap; + this.meta = meta; + this.stdlib = stdlib; + this.labelsStack = new Stack(); + this.encoder = new InstructionEncoderImpl([]); + this.errors = []; + this.handle = heap.malloc(); + } + + error(error) { + this.encoder.encode(30 + /* Primitive */ + , 0); + this.errors.push(error); + } + + commit(size) { + let handle = this.handle; + this.heap.push(5 + /* Return */ + | 1024 + /* MACHINE_MASK */ + ); + this.heap.finishMalloc(handle, size); + + if (this.errors.length) { + return { + errors: this.errors, + handle + }; + } else { + return handle; + } + } + + push(constants, type, ...args) { + let { + heap + } = this; + + if (DEBUG && type > 255 + /* TYPE_SIZE */ + ) { + throw new Error(`Opcode type over 8-bits. Got ${type}.`); + } + + let machine = isMachineOp(type) ? 1024 + /* MACHINE_MASK */ + : 0; + let first = type | machine | args.length << 8 + /* ARG_SHIFT */ + ; + heap.push(first); + + for (let i = 0; i < args.length; i++) { + let op = args[i]; + heap.push(this.operand(constants, op)); + } + } + + operand(constants, operand) { + if (typeof operand === 'number') { + return operand; + } + + if (typeof operand === 'object' && operand !== null) { + if (Array.isArray(operand)) { + return encodeHandle(constants.array(operand)); + } else { + switch (operand.type) { + case 1 + /* Label */ + : + this.currentLabels.target(this.heap.offset, operand.value); + return -1; + + case 2 + /* IsStrictMode */ + : + return encodeHandle(constants.value(this.meta.isStrictMode)); + + case 3 + /* EvalSymbols */ + : + return encodeHandle(constants.array(this.meta.evalSymbols || EMPTY_STRING_ARRAY)); + + case 4 + /* Block */ + : + return encodeHandle(constants.value(compilableBlock(operand.value, this.meta))); + + case 5 + /* StdLib */ + : + return this.stdlib[operand.value]; + + case 6 + /* NonSmallInt */ + : + case 7 + /* SymbolTable */ + : + case 8 + /* Layout */ + : + return constants.value(operand.value); + } + } + } + + return encodeHandle(constants.value(operand)); + } + + get currentLabels() { + return this.labelsStack.current; + } + + label(name) { + this.currentLabels.label(name, this.heap.offset + 1); + } + + startLabels() { + this.labelsStack.push(new Labels()); + } + + stopLabels() { + let label = this.labelsStack.pop(); + label.patch(this.heap); + } + +} + +function isBuilderOpcode(op) { + return op < 1000 + /* Start */ + ; +} + +function main(op) { + op(75 + /* Main */ + , $s0); + invokePreparedComponent(op, false, false, true); +} +/** + * Append content to the DOM. This standard function triages content and does the + * right thing based upon whether it's a string, safe string, component, fragment + * or node. + * + * @param trusting whether to interpolate a string as raw HTML (corresponds to + * triple curlies) + */ + +function StdAppend(op, trusting, nonDynamicAppend) { + SwitchCases(op, () => op(76 + /* ContentType */ + ), when => { + when(2 + /* String */ + , () => { + if (trusting) { + op(68 + /* AssertSame */ + ); + op(43 + /* AppendHTML */ + ); + } else { + op(47 + /* AppendText */ + ); + } + }); + + if (typeof nonDynamicAppend === 'number') { + when(0 + /* Component */ + , () => { + op(81 + /* ResolveCurriedComponent */ + ); + op(79 + /* PushDynamicComponentInstance */ + ); + InvokeBareComponent(op); + }); + when(1 + /* Helper */ + , () => { + CallDynamic(op, null, null, () => { + op(3 + /* InvokeStatic */ + , nonDynamicAppend); + }); + }); + } else { + // when non-dynamic, we can no longer call the value (potentially because we've already called it) + // this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM. + when(0 + /* Component */ + , () => { + op(47 + /* AppendText */ + ); + }); + when(1 + /* Helper */ + , () => { + op(47 + /* AppendText */ + ); + }); + } + + when(4 + /* SafeString */ + , () => { + op(68 + /* AssertSame */ + ); + op(44 + /* AppendSafeHTML */ + ); + }); + when(5 + /* Fragment */ + , () => { + op(68 + /* AssertSame */ + ); + op(45 + /* AppendDocumentFragment */ + ); + }); + when(6 + /* Node */ + , () => { + op(68 + /* AssertSame */ + ); + op(46 + /* AppendNode */ + ); + }); + }); +} +function compileStd(context) { + let mainHandle = build(context, op => main(op)); + let trustingGuardedNonDynamicAppend = build(context, op => StdAppend(op, true, null)); + let cautiousGuardedNonDynamicAppend = build(context, op => StdAppend(op, false, null)); + let trustingGuardedDynamicAppend = build(context, op => StdAppend(op, true, trustingGuardedNonDynamicAppend)); + let cautiousGuardedDynamicAppend = build(context, op => StdAppend(op, false, cautiousGuardedNonDynamicAppend)); + return new StdLib(mainHandle, trustingGuardedDynamicAppend, cautiousGuardedDynamicAppend, trustingGuardedNonDynamicAppend, cautiousGuardedNonDynamicAppend); +} +const STDLIB_META = { + asPartial: false, + evalSymbols: null, + upvars: null, + moduleName: 'stdlib', + // TODO: ?? + scopeValues: null, + isStrictMode: true, + owner: null, + size: 0 +}; + +function build(program, callback) { + let { + constants, + heap, + resolver + } = program; + let encoder = new EncoderImpl(heap, STDLIB_META); + + function pushOp(...op) { + encodeOp(encoder, constants, resolver, STDLIB_META, op); + } + + callback(pushOp); + let result = encoder.commit(0); + + if (typeof result !== 'number') { + // This shouldn't be possible + throw new Error(`Unexpected errors compiling std`); + } else { + return result; + } +} + +class CompileTimeCompilationContextImpl { + constructor({ + constants, + heap + }, resolver) { + this.resolver = resolver; + this.constants = constants; + this.heap = heap; + this.stdlib = compileStd(this); + } + +} + +const DEFAULT_CAPABILITIES = { + dynamicLayout: true, + dynamicTag: true, + prepareArgs: true, + createArgs: true, + attributeHook: false, + elementHook: false, + dynamicScope: true, + createCaller: false, + updateHook: true, + createInstance: true, + wrapped: false, + willDestroy: false, + hasSubOwner: false +}; +const MINIMAL_CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false, + dynamicScope: false, + createCaller: false, + updateHook: false, + createInstance: false, + wrapped: false, + willDestroy: false, + hasSubOwner: false +}; + +class PartialDefinitionImpl { + constructor(name, // for debugging + template) { + this.name = name; + this.template = template; + } + + getPartial(context) { + let partial = unwrapTemplate(this.template).asPartial(); + let handle = partial.compile(context); + return { + symbolTable: partial.symbolTable, + handle + }; + } + +} + +class WrappedBuilder { + constructor(layout, moduleName) { + this.layout = layout; + this.moduleName = moduleName; + this.compiled = null; + let { + block + } = layout; + let [, symbols, hasEval] = block; + symbols = symbols.slice(); // ensure ATTRS_BLOCK is always included (only once) in the list of symbols + + let attrsBlockIndex = symbols.indexOf(ATTRS_BLOCK); + + if (attrsBlockIndex === -1) { + this.attrsBlockNumber = symbols.push(ATTRS_BLOCK); + } else { + this.attrsBlockNumber = attrsBlockIndex + 1; + } + + this.symbolTable = { + hasEval, + symbols + }; + } + + compile(syntax) { + if (this.compiled !== null) return this.compiled; + let m = meta(this.layout); + let context = templateCompilationContext(syntax, m); + let { + encoder, + program: { + constants, + resolver + } + } = context; + + function pushOp(...op) { + encodeOp(encoder, constants, resolver, m, op); + } + + WrappedComponent(pushOp, this.layout, this.attrsBlockNumber); + let handle = context.encoder.commit(m.size); + + if (typeof handle !== 'number') { + return handle; + } + + this.compiled = handle; + + return handle; + } + +} + +let clientId = 0; +let templateCacheCounters = { + cacheHit: 0, + cacheMiss: 0 +}; +/** + * Wraps a template js in a template module to change it into a factory + * that handles lazy parsing the template and to create per env singletons + * of the template. + */ + +function templateFactory({ + id: templateId, + moduleName, + block, + scope, + isStrictMode +}) { + // TODO(template-refactors): This should be removed in the near future, as it + // appears that id is unused. It is currently kept for backwards compat reasons. + let id = templateId || `client-${clientId++}`; // TODO: This caches JSON serialized output once in case a template is + // compiled by multiple owners, but we haven't verified if this is actually + // helpful. We should benchmark this in the future. + + let parsedBlock; + let ownerlessTemplate = null; + let templateCache = new WeakMap(); + + let factory = owner => { + if (parsedBlock === undefined) { + parsedBlock = JSON.parse(block); + } + + if (owner === undefined) { + if (ownerlessTemplate === null) { + templateCacheCounters.cacheMiss++; + ownerlessTemplate = new TemplateImpl({ + id, + block: parsedBlock, + moduleName, + owner: null, + scope, + isStrictMode + }); + } else { + templateCacheCounters.cacheHit++; + } + + return ownerlessTemplate; + } + + let result = templateCache.get(owner); + + if (result === undefined) { + templateCacheCounters.cacheMiss++; + result = new TemplateImpl({ + id, + block: parsedBlock, + moduleName, + owner, + scope, + isStrictMode + }); + templateCache.set(owner, result); + } else { + templateCacheCounters.cacheHit++; + } + + return result; + }; + + factory.__id = id; + factory.__meta = { + moduleName + }; + return factory; +} + +class TemplateImpl { + constructor(parsedLayout) { + this.parsedLayout = parsedLayout; + this.result = 'ok'; + this.layout = null; + this.partial = null; + this.wrappedLayout = null; + } + + get moduleName() { + return this.parsedLayout.moduleName; + } + + get id() { + return this.parsedLayout.id; + } // TODO(template-refactors): This should be removed in the near future, it is + // only being exposed for backwards compatibility + + + get referrer() { + return { + moduleName: this.parsedLayout.moduleName, + owner: this.parsedLayout.owner + }; + } + + asLayout() { + if (this.layout) return this.layout; + return this.layout = compilable(assign({}, this.parsedLayout, { + asPartial: false + }), this.moduleName); + } + + asPartial() { + if (this.partial) return this.partial; + return this.partial = compilable(assign({}, this.parsedLayout, { + asPartial: true + }), this.moduleName); + } + + asWrappedLayout() { + if (this.wrappedLayout) return this.wrappedLayout; + return this.wrappedLayout = new WrappedBuilder(assign({}, this.parsedLayout, { + asPartial: false + }), this.moduleName); + } + +} + +export { debugCompiler, compileStatements, compilable, InvokeStaticBlockWithStack as invokeStaticBlockWithStack, InvokeStaticBlock as invokeStaticBlock, compileStd, meta, StdLib, PartialDefinitionImpl, templateFactory, templateCacheCounters, WrappedBuilder, EMPTY_BLOCKS, CompileTimeCompilationContextImpl, programCompilationContext, templateCompilationContext, DEFAULT_CAPABILITIES, MINIMAL_CAPABILITIES }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/owner.js b/ember-vendored-pr-19806/dependencies/@glimmer/owner.js new file mode 100644 index 0000000..9b1a550 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/owner.js @@ -0,0 +1,21 @@ +import { symbol } from '@glimmer/util'; + +const OWNER = symbol('OWNER'); +/** + Framework objects in a Glimmer application may receive an owner object. + Glimmer is unopinionated about this owner, but will forward it through its + internal resolution system, and through its managers if it is provided. +*/ + +function getOwner(object) { + return object[OWNER]; +} +/** + `setOwner` set's an object's owner +*/ + +function setOwner(object, owner) { + object[OWNER] = owner; +} + +export { OWNER, getOwner, setOwner }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/program.js b/ember-vendored-pr-19806/dependencies/@glimmer/program.js new file mode 100644 index 0000000..a9a7e55 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/program.js @@ -0,0 +1,519 @@ +import { constants, unwrapTemplate } from '@glimmer/util'; +import { capabilityFlagsFrom, getComponentTemplate, getInternalComponentManager, getInternalHelperManager, getInternalModifierManager, managerHasCapability } from '@glimmer/manager'; +import { templateFactory } from '@glimmer/opcode-compiler'; + +/** + * Default component template, which is a plain yield + */ +const DEFAULT_TEMPLATE_BLOCK = [[[18 +/* Yield */ +, 1, null]], ['&default'], false, []]; +const DEFAULT_TEMPLATE = { + // random uuid + id: '1b32f5c2-7623-43d6-a0ad-9672898920a1', + moduleName: '__default__.hbs', + block: JSON.stringify(DEFAULT_TEMPLATE_BLOCK), + scope: null, + isStrictMode: true +}; + +const WELL_KNOWN_EMPTY_ARRAY = Object.freeze([]); +const STARTER_CONSTANTS = constants(WELL_KNOWN_EMPTY_ARRAY); +const WELL_KNOWN_EMPTY_ARRAY_POSITION = STARTER_CONSTANTS.indexOf(WELL_KNOWN_EMPTY_ARRAY); +class CompileTimeConstantImpl { + constructor() { + // `0` means NULL + this.values = STARTER_CONSTANTS.slice(); + this.indexMap = new Map(this.values.map((value, index) => [value, index])); + } + + value(value) { + let indexMap = this.indexMap; + let index = indexMap.get(value); + + if (index === undefined) { + index = this.values.push(value) - 1; + indexMap.set(value, index); + } + + return index; + } + + array(values) { + if (values.length === 0) { + return WELL_KNOWN_EMPTY_ARRAY_POSITION; + } + + let handles = new Array(values.length); + + for (let i = 0; i < values.length; i++) { + handles[i] = this.value(values[i]); + } + + return this.value(handles); + } + + toPool() { + return this.values; + } + +} +class RuntimeConstantsImpl { + constructor(pool) { + this.values = pool; + } + + getValue(handle) { + return this.values[handle]; + } + + getArray(value) { + let handles = this.getValue(value); + let reified = new Array(handles.length); + + for (let i = 0; i < handles.length; i++) { + let n = handles[i]; + reified[i] = this.getValue(n); + } + + return reified; + } + +} +class ConstantsImpl extends CompileTimeConstantImpl { + constructor() { + super(...arguments); + this.reifiedArrs = { + [WELL_KNOWN_EMPTY_ARRAY_POSITION]: WELL_KNOWN_EMPTY_ARRAY + }; + this.defaultTemplate = templateFactory(DEFAULT_TEMPLATE)(); // Used for tests and debugging purposes, and to be able to analyze large apps + // This is why it's enabled even in production + + this.helperDefinitionCount = 0; + this.modifierDefinitionCount = 0; + this.componentDefinitionCount = 0; + this.helperDefinitionCache = new WeakMap(); + this.modifierDefinitionCache = new WeakMap(); + this.componentDefinitionCache = new WeakMap(); + } + + helper(definitionState, // TODO: Add a way to expose resolved name for debugging + _resolvedName = null, isOptional) { + let handle = this.helperDefinitionCache.get(definitionState); + + if (handle === undefined) { + let managerOrHelper = getInternalHelperManager(definitionState, isOptional); + + if (managerOrHelper === null) { + this.helperDefinitionCache.set(definitionState, null); + return null; + } + let helper = typeof managerOrHelper === 'function' ? managerOrHelper : managerOrHelper.getHelper(definitionState); + handle = this.value(helper); + this.helperDefinitionCache.set(definitionState, handle); + this.helperDefinitionCount++; + } + + return handle; + } + + modifier(definitionState, resolvedName = null, isOptional) { + let handle = this.modifierDefinitionCache.get(definitionState); + + if (handle === undefined) { + let manager = getInternalModifierManager(definitionState, isOptional); + + if (manager === null) { + this.modifierDefinitionCache.set(definitionState, null); + return null; + } + + let definition = { + resolvedName, + manager, + state: definitionState + }; + handle = this.value(definition); + this.modifierDefinitionCache.set(definitionState, handle); + this.modifierDefinitionCount++; + } + + return handle; + } + + component(definitionState, owner, isOptional) { + var _a; + + let definition = this.componentDefinitionCache.get(definitionState); + + if (definition === undefined) { + let manager = getInternalComponentManager(definitionState, isOptional); + + if (manager === null) { + this.componentDefinitionCache.set(definitionState, null); + return null; + } + let capabilities = capabilityFlagsFrom(manager.getCapabilities(definitionState)); + let templateFactory$$1 = getComponentTemplate(definitionState); + let compilable = null; + let template; + + if (!managerHasCapability(manager, capabilities, 1 + /* DynamicLayout */ + )) { + template = (_a = templateFactory$$1 === null || templateFactory$$1 === void 0 ? void 0 : templateFactory$$1(owner)) !== null && _a !== void 0 ? _a : this.defaultTemplate; + } else { + template = templateFactory$$1 === null || templateFactory$$1 === void 0 ? void 0 : templateFactory$$1(owner); + } + + if (template !== undefined) { + template = unwrapTemplate(template); + compilable = managerHasCapability(manager, capabilities, 1024 + /* Wrapped */ + ) ? template.asWrappedLayout() : template.asLayout(); + } + + definition = { + resolvedName: null, + handle: -1, + manager, + capabilities, + state: definitionState, + compilable + }; + definition.handle = this.value(definition); + this.componentDefinitionCache.set(definitionState, definition); + this.componentDefinitionCount++; + } + + return definition; + } + + resolvedComponent(resolvedDefinition, resolvedName) { + let definition = this.componentDefinitionCache.get(resolvedDefinition); + + if (definition === undefined) { + let { + manager, + state, + template + } = resolvedDefinition; + let capabilities = capabilityFlagsFrom(manager.getCapabilities(resolvedDefinition)); + let compilable = null; + + if (!managerHasCapability(manager, capabilities, 1 + /* DynamicLayout */ + )) { + template = template !== null && template !== void 0 ? template : this.defaultTemplate; + } + + if (template !== null) { + template = unwrapTemplate(template); + compilable = managerHasCapability(manager, capabilities, 1024 + /* Wrapped */ + ) ? template.asWrappedLayout() : template.asLayout(); + } + + definition = { + resolvedName, + handle: -1, + manager, + capabilities, + state, + compilable + }; + definition.handle = this.value(definition); + this.componentDefinitionCache.set(resolvedDefinition, definition); + this.componentDefinitionCount++; + } + + return definition; + } + + getValue(index) { + return this.values[index]; + } + + getArray(index) { + let reifiedArrs = this.reifiedArrs; + let reified = reifiedArrs[index]; + + if (reified === undefined) { + let names = this.getValue(index); + reified = new Array(names.length); + + for (let i = 0; i < names.length; i++) { + reified[i] = this.getValue(names[i]); + } + + reifiedArrs[index] = reified; + } + + return reified; + } + +} + +class RuntimeOpImpl { + constructor(heap) { + this.heap = heap; + this.offset = 0; + } + + get size() { + let rawType = this.heap.getbyaddr(this.offset); + return ((rawType & 768 + /* OPERAND_LEN_MASK */ + ) >> 8 + /* ARG_SHIFT */ + ) + 1; + } + + get isMachine() { + let rawType = this.heap.getbyaddr(this.offset); + return rawType & 1024 + /* MACHINE_MASK */ + ? 1 : 0; + } + + get type() { + return this.heap.getbyaddr(this.offset) & 255 + /* TYPE_MASK */ + ; + } + + get op1() { + return this.heap.getbyaddr(this.offset + 1); + } + + get op2() { + return this.heap.getbyaddr(this.offset + 2); + } + + get op3() { + return this.heap.getbyaddr(this.offset + 3); + } + +} + +const PAGE_SIZE = 0x100000; +class RuntimeHeapImpl { + constructor(serializedHeap) { + let { + buffer, + table + } = serializedHeap; + this.heap = new Int32Array(buffer); + this.table = table; + } // It is illegal to close over this address, as compaction + // may move it. However, it is legal to use this address + // multiple times between compactions. + + + getaddr(handle) { + return this.table[handle]; + } + + getbyaddr(address) { + return this.heap[address]; + } + + sizeof(handle) { + return sizeof(this.table, handle); + } + +} +function hydrateHeap(serializedHeap) { + return new RuntimeHeapImpl(serializedHeap); +} +/** + * The Heap is responsible for dynamically allocating + * memory in which we read/write the VM's instructions + * from/to. When we malloc we pass out a VMHandle, which + * is used as an indirect way of accessing the memory during + * execution of the VM. Internally we track the different + * regions of the memory in an int array known as the table. + * + * The table 32-bit aligned and has the following layout: + * + * | ... | hp (u32) | info (u32) | size (u32) | + * | ... | Handle | Scope Size | State | Size | + * | ... | 32bits | 30bits | 2bits | 32bit | + * + * With this information we effectively have the ability to + * control when we want to free memory. That being said you + * can not free during execution as raw address are only + * valid during the execution. This means you cannot close + * over them as you will have a bad memory access exception. + */ + +class HeapImpl { + constructor() { + this.offset = 0; + this.handle = 0; + this.heap = new Int32Array(PAGE_SIZE); + this.handleTable = []; + this.handleState = []; + } + + push(item) { + this.sizeCheck(); + this.heap[this.offset++] = item; + } + + sizeCheck() { + let { + heap + } = this; + + if (this.offset === this.heap.length) { + let newHeap = new Int32Array(heap.length + PAGE_SIZE); + newHeap.set(heap, 0); + this.heap = newHeap; + } + } + + getbyaddr(address) { + return this.heap[address]; + } + + setbyaddr(address, value) { + this.heap[address] = value; + } + + malloc() { + // push offset, info, size + this.handleTable.push(this.offset); + return this.handleTable.length - 1; + } + + finishMalloc(handle) { + } + + size() { + return this.offset; + } // It is illegal to close over this address, as compaction + // may move it. However, it is legal to use this address + // multiple times between compactions. + + + getaddr(handle) { + return this.handleTable[handle]; + } + + sizeof(handle) { + return sizeof(this.handleTable, handle); + } + + free(handle) { + this.handleState[handle] = 1 + /* Freed */ + ; + } + /** + * The heap uses the [Mark-Compact Algorithm](https://en.wikipedia.org/wiki/Mark-compact_algorithm) to shift + * reachable memory to the bottom of the heap and freeable + * memory to the top of the heap. When we have shifted all + * the reachable memory to the top of the heap, we move the + * offset to the next free position. + */ + + + compact() { + let compactedSize = 0; + let { + handleTable, + handleState, + heap + } = this; + + for (let i = 0; i < length; i++) { + let offset = handleTable[i]; + let size = handleTable[i + 1] - offset; + let state = handleState[i]; + + if (state === 2 + /* Purged */ + ) { + continue; + } else if (state === 1 + /* Freed */ + ) { + // transition to "already freed" aka "purged" + // a good improvement would be to reuse + // these slots + handleState[i] = 2 + /* Purged */ + ; + compactedSize += size; + } else if (state === 0 + /* Allocated */ + ) { + for (let j = offset; j <= i + size; j++) { + heap[j - compactedSize] = heap[j]; + } + + handleTable[i] = offset - compactedSize; + } else if (state === 3 + /* Pointer */ + ) { + handleTable[i] = offset - compactedSize; + } + } + + this.offset = this.offset - compactedSize; + } + + capture(offset = this.offset) { + // Only called in eager mode + let buffer = slice(this.heap, 0, offset).buffer; + return { + handle: this.handle, + table: this.handleTable, + buffer: buffer + }; + } + +} +class RuntimeProgramImpl { + constructor(constants$$1, heap) { + this.constants = constants$$1; + this.heap = heap; + this._opcode = new RuntimeOpImpl(this.heap); + } + + opcode(offset) { + this._opcode.offset = offset; + return this._opcode; + } + +} + +function slice(arr, start, end) { + if (arr.slice !== undefined) { + return arr.slice(start, end); + } + + let ret = new Int32Array(end); + + for (; start < end; start++) { + ret[start] = arr[start]; + } + + return ret; +} + +function sizeof(table, handle) { + { + return -1; + } +} + +function artifacts() { + return { + constants: new ConstantsImpl(), + heap: new HeapImpl() + }; +} + +export { CompileTimeConstantImpl, RuntimeConstantsImpl, ConstantsImpl, RuntimeHeapImpl, hydrateHeap, HeapImpl, RuntimeProgramImpl, RuntimeOpImpl, artifacts }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/reference.js b/ember-vendored-pr-19806/dependencies/@glimmer/reference.js new file mode 100644 index 0000000..0e67431 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/reference.js @@ -0,0 +1,440 @@ +import { DEBUG } from '@glimmer/env'; +import { getProp, setProp, getPath, toIterator } from '@glimmer/global-context'; +import { isDict, symbol, EMPTY_ARRAY, isObject } from '@glimmer/util'; +import { CONSTANT_TAG, consumeTag, INITIAL, track, validateTag, valueForTag, createTag, dirtyTag } from '@glimmer/validator'; + +const REFERENCE = symbol('REFERENCE'); + +class ReferenceImpl { + constructor(type) { + this.tag = null; + this.lastRevision = INITIAL; + this.children = null; + this.compute = null; + this.update = null; + this[REFERENCE] = type; + } + +} + +function createPrimitiveRef(value) { + let ref = new ReferenceImpl(2 + /* Unbound */ + ); + ref.tag = CONSTANT_TAG; + ref.lastValue = value; + + if (DEBUG) { + ref.debugLabel = String(value); + } + + return ref; +} +const UNDEFINED_REFERENCE = createPrimitiveRef(undefined); +const NULL_REFERENCE = createPrimitiveRef(null); +const TRUE_REFERENCE = createPrimitiveRef(true); +const FALSE_REFERENCE = createPrimitiveRef(false); +function createConstRef(value, debugLabel) { + let ref = new ReferenceImpl(0 + /* Constant */ + ); + ref.lastValue = value; + ref.tag = CONSTANT_TAG; + + if (DEBUG) { + ref.debugLabel = debugLabel; + } + + return ref; +} +function createUnboundRef(value, debugLabel) { + let ref = new ReferenceImpl(2 + /* Unbound */ + ); + ref.lastValue = value; + ref.tag = CONSTANT_TAG; + + if (DEBUG) { + ref.debugLabel = debugLabel; + } + + return ref; +} +function createComputeRef(compute, update = null, debugLabel = 'unknown') { + let ref = new ReferenceImpl(1 + /* Compute */ + ); + ref.compute = compute; + ref.update = update; + + if (DEBUG) { + ref.debugLabel = `(result of a \`${debugLabel}\` helper)`; + } + + return ref; +} +function createReadOnlyRef(ref) { + if (!isUpdatableRef(ref)) return ref; + return createComputeRef(() => valueForRef(ref), null, ref.debugLabel); +} +function isInvokableRef(ref) { + return ref[REFERENCE] === 3 + /* Invokable */ + ; +} +function createInvokableRef(inner) { + let ref = createComputeRef(() => valueForRef(inner), value => updateRef(inner, value)); + ref.debugLabel = inner.debugLabel; + ref[REFERENCE] = 3 + /* Invokable */ + ; + return ref; +} +function isConstRef(_ref) { + let ref = _ref; + return ref.tag === CONSTANT_TAG; +} +function isUpdatableRef(_ref) { + let ref = _ref; + return ref.update !== null; +} +function valueForRef(_ref) { + let ref = _ref; + let { + tag + } = ref; + + if (tag === CONSTANT_TAG) { + return ref.lastValue; + } + + let { + lastRevision + } = ref; + let lastValue; + + if (tag === null || !validateTag(tag, lastRevision)) { + let { + compute + } = ref; + tag = ref.tag = track(() => { + lastValue = ref.lastValue = compute(); + }, DEBUG && ref.debugLabel); + ref.lastRevision = valueForTag(tag); + } else { + lastValue = ref.lastValue; + } + + consumeTag(tag); + return lastValue; +} +function updateRef(_ref, value) { + let ref = _ref; + let update = ref.update; + update(value); +} +function childRefFor(_parentRef, path) { + let parentRef = _parentRef; + let type = parentRef[REFERENCE]; + let children = parentRef.children; + let child; + + if (children === null) { + children = parentRef.children = new Map(); + } else { + child = children.get(path); + + if (child !== undefined) { + return child; + } + } + + if (type === 2 + /* Unbound */ + ) { + let parent = valueForRef(parentRef); + + if (isDict(parent)) { + child = createUnboundRef(parent[path], DEBUG && `${parentRef.debugLabel}.${path}`); + } else { + child = UNDEFINED_REFERENCE; + } + } else { + child = createComputeRef(() => { + let parent = valueForRef(parentRef); + + if (isDict(parent)) { + return getProp(parent, path); + } + }, val => { + let parent = valueForRef(parentRef); + + if (isDict(parent)) { + return setProp(parent, path, val); + } + }); + + if (DEBUG) { + child.debugLabel = `${parentRef.debugLabel}.${path}`; + } + } + + children.set(path, child); + return child; +} +function childRefFromParts(root, parts) { + let reference = root; + + for (let i = 0; i < parts.length; i++) { + reference = childRefFor(reference, parts[i]); + } + + return reference; +} +let createDebugAliasRef; + +if (DEBUG) { + createDebugAliasRef = (debugLabel, inner) => { + let update = isUpdatableRef(inner) ? value => updateRef(inner, value) : null; + let ref = createComputeRef(() => valueForRef(inner), update); + ref[REFERENCE] = inner[REFERENCE]; + ref.debugLabel = debugLabel; + return ref; + }; +} + +const NULL_IDENTITY = {}; + +const KEY = (_, index) => index; + +const INDEX = (_, index) => String(index); + +const IDENTITY = item => { + if (item === null) { + // Returning null as an identity will cause failures since the iterator + // can't tell that it's actually supposed to be null + return NULL_IDENTITY; + } + + return item; +}; + +function keyForPath(path) { + if (DEBUG && path[0] === '@') { + throw new Error(`invalid keypath: '${path}', valid keys: @index, @identity, or a path`); + } + + return uniqueKeyFor(item => getPath(item, path)); +} + +function makeKeyFor(key) { + switch (key) { + case '@key': + return uniqueKeyFor(KEY); + + case '@index': + return uniqueKeyFor(INDEX); + + case '@identity': + return uniqueKeyFor(IDENTITY); + + default: + return keyForPath(key); + } +} + +class WeakMapWithPrimitives { + get weakMap() { + if (this._weakMap === undefined) { + this._weakMap = new WeakMap(); + } + + return this._weakMap; + } + + get primitiveMap() { + if (this._primitiveMap === undefined) { + this._primitiveMap = new Map(); + } + + return this._primitiveMap; + } + + set(key, value) { + if (isObject(key)) { + this.weakMap.set(key, value); + } else { + this.primitiveMap.set(key, value); + } + } + + get(key) { + if (isObject(key)) { + return this.weakMap.get(key); + } else { + return this.primitiveMap.get(key); + } + } + +} + +const IDENTITIES = new WeakMapWithPrimitives(); + +function identityForNthOccurence(value, count) { + let identities = IDENTITIES.get(value); + + if (identities === undefined) { + identities = []; + IDENTITIES.set(value, identities); + } + + let identity = identities[count]; + + if (identity === undefined) { + identity = { + value, + count + }; + identities[count] = identity; + } + + return identity; +} +/** + * When iterating over a list, it's possible that an item with the same unique + * key could be encountered twice: + * + * ```js + * let arr = ['same', 'different', 'same', 'same']; + * ``` + * + * In general, we want to treat these items as _unique within the list_. To do + * this, we track the occurences of every item as we iterate the list, and when + * an item occurs more than once, we generate a new unique key just for that + * item, and that occurence within the list. The next time we iterate the list, + * and encounter an item for the nth time, we can get the _same_ key, and let + * Glimmer know that it should reuse the DOM for the previous nth occurence. + */ + + +function uniqueKeyFor(keyFor) { + let seen = new WeakMapWithPrimitives(); + return (value, memo) => { + let key = keyFor(value, memo); + let count = seen.get(key) || 0; + seen.set(key, count + 1); + + if (count === 0) { + return key; + } + + return identityForNthOccurence(key, count); + }; +} + +function createIteratorRef(listRef, key) { + return createComputeRef(() => { + let iterable = valueForRef(listRef); + let keyFor = makeKeyFor(key); + + if (Array.isArray(iterable)) { + return new ArrayIterator(iterable, keyFor); + } + + let maybeIterator = toIterator(iterable); + + if (maybeIterator === null) { + return new ArrayIterator(EMPTY_ARRAY, () => null); + } + + return new IteratorWrapper(maybeIterator, keyFor); + }); +} +function createIteratorItemRef(_value) { + let value = _value; + let tag = createTag(); + return createComputeRef(() => { + consumeTag(tag); + return value; + }, newValue => { + if (value !== newValue) { + value = newValue; + dirtyTag(tag); + } + }); +} + +class IteratorWrapper { + constructor(inner, keyFor) { + this.inner = inner; + this.keyFor = keyFor; + } + + isEmpty() { + return this.inner.isEmpty(); + } + + next() { + let nextValue = this.inner.next(); + + if (nextValue !== null) { + nextValue.key = this.keyFor(nextValue.value, nextValue.memo); + } + + return nextValue; + } + +} + +class ArrayIterator { + constructor(iterator, keyFor) { + this.iterator = iterator; + this.keyFor = keyFor; + this.pos = 0; + + if (iterator.length === 0) { + this.current = { + kind: 'empty' + }; + } else { + this.current = { + kind: 'first', + value: iterator[this.pos] + }; + } + } + + isEmpty() { + return this.current.kind === 'empty'; + } + + next() { + let value; + let current = this.current; + + if (current.kind === 'first') { + this.current = { + kind: 'progress' + }; + value = current.value; + } else if (this.pos >= this.iterator.length - 1) { + return null; + } else { + value = this.iterator[++this.pos]; + } + + let { + keyFor + } = this; + let key = keyFor(value, this.pos); + let memo = this.pos; + return { + key, + value, + memo + }; + } + +} + +export { REFERENCE, createPrimitiveRef, createConstRef, createUnboundRef, createComputeRef, createDebugAliasRef, createReadOnlyRef, createInvokableRef, isInvokableRef, isConstRef, isUpdatableRef, valueForRef, updateRef, childRefFor, childRefFromParts, UNDEFINED_REFERENCE, NULL_REFERENCE, TRUE_REFERENCE, FALSE_REFERENCE, createIteratorRef, createIteratorItemRef }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/runtime.js b/ember-vendored-pr-19806/dependencies/@glimmer/runtime.js new file mode 100644 index 0000000..89ddb8f --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/runtime.js @@ -0,0 +1,7290 @@ +import { assign, symbol, Stack, fillNulls, _WeakSet, isObject, dict, emptyArray, EMPTY_STRING_ARRAY, debugToString, decodeHandle, decodeImmediate, isHandle, unwrapTemplate, unwrapHandle, clearElement, buildUntouchableThis, HAS_NATIVE_PROXY, isDict } from '@glimmer/util'; +import { UNDEFINED_REFERENCE, valueForRef, createComputeRef, createDebugAliasRef, childRefFor, TRUE_REFERENCE, FALSE_REFERENCE, isConstRef, createPrimitiveRef, NULL_REFERENCE, createConstRef, createIteratorRef, updateRef, createIteratorItemRef, isInvokableRef } from '@glimmer/reference'; +import { warnIfStyleNotTrusted, toBool, assertGlobalContextWasSet, deprecate, getPath, setPath } from '@glimmer/global-context'; +import { DEBUG } from '@glimmer/env'; +import { destroy, registerDestructor, associateDestroyableChild, _hasDestroyableChildren, destroyChildren, isDestroyed, isDestroying } from '@glimmer/destroyable'; +export { destroy, registerDestructor, isDestroying, isDestroyed } from '@glimmer/destroyable'; +import { $fp, $pc, $ra, $sp, $v0, $t0, $t1, $s0, $s1, isLowLevelRegister } from '@glimmer/vm'; +import { CONSTANT_TAG, valueForTag, validateTag, INITIAL, beginTrackFrame, endTrackFrame, consumeTag, CURRENT_TAG, track, updateTag, resetTracking, runInTrackingTransaction, createCache, getValue, createUpdatableTag } from '@glimmer/validator'; +import { managerHasCapability, hasInternalComponentManager, hasInternalHelperManager, setInternalComponentManager, getInternalHelperManager, hasDestroyable, hasValue, setInternalHelperManager, setInternalModifierManager } from '@glimmer/manager'; +import { RuntimeProgramImpl } from '@glimmer/program'; +import { getOwner } from '@glimmer/owner'; +import { reifyPositional, reifyNamed } from '@glimmer/runtime'; + +class DynamicScopeImpl { + constructor(bucket) { + if (bucket) { + this.bucket = assign({}, bucket); + } else { + this.bucket = {}; + } + } + + get(key) { + return this.bucket[key]; + } + + set(key, reference) { + return this.bucket[key] = reference; + } + + child() { + return new DynamicScopeImpl(this.bucket); + } + +} +class PartialScopeImpl { + constructor( // the 0th slot is `self` + slots, owner, callerScope, // named arguments and blocks passed to a layout that uses eval + evalScope, // locals in scope when the partial was invoked + partialMap) { + this.slots = slots; + this.owner = owner; + this.callerScope = callerScope; + this.evalScope = evalScope; + this.partialMap = partialMap; + } + + static root(self, size = 0, owner) { + let refs = new Array(size + 1); + + for (let i = 0; i <= size; i++) { + refs[i] = UNDEFINED_REFERENCE; + } + + return new PartialScopeImpl(refs, owner, null, null, null).init({ + self + }); + } + + static sized(size = 0, owner) { + let refs = new Array(size + 1); + + for (let i = 0; i <= size; i++) { + refs[i] = UNDEFINED_REFERENCE; + } + + return new PartialScopeImpl(refs, owner, null, null, null); + } + + init({ + self + }) { + this.slots[0] = self; + return this; + } + + getSelf() { + return this.get(0); + } + + getSymbol(symbol$$1) { + return this.get(symbol$$1); + } + + getBlock(symbol$$1) { + let block = this.get(symbol$$1); + return block === UNDEFINED_REFERENCE ? null : block; + } + + getEvalScope() { + return this.evalScope; + } + + getPartialMap() { + return this.partialMap; + } + + bind(symbol$$1, value) { + this.set(symbol$$1, value); + } + + bindSelf(self) { + this.set(0, self); + } + + bindSymbol(symbol$$1, value) { + this.set(symbol$$1, value); + } + + bindBlock(symbol$$1, value) { + this.set(symbol$$1, value); + } + + bindEvalScope(map) { + this.evalScope = map; + } + + bindPartialMap(map) { + this.partialMap = map; + } + + bindCallerScope(scope) { + this.callerScope = scope; + } + + getCallerScope() { + return this.callerScope; + } + + child() { + return new PartialScopeImpl(this.slots.slice(), this.owner, this.callerScope, this.evalScope, this.partialMap); + } + + get(index) { + if (index >= this.slots.length) { + throw new RangeError(`BUG: cannot get $${index} from scope; length=${this.slots.length}`); + } + + return this.slots[index]; + } + + set(index, value) { + if (index >= this.slots.length) { + throw new RangeError(`BUG: cannot get $${index} from scope; length=${this.slots.length}`); + } + + this.slots[index] = value; + } + +} + +// the VM in other classes, but are not intended to be a part of +// Glimmer's API. + +const INNER_VM = symbol('INNER_VM'); +const DESTROYABLE_STACK = symbol('DESTROYABLE_STACK'); +const STACKS = symbol('STACKS'); +const REGISTERS = symbol('REGISTERS'); +const HEAP = symbol('HEAP'); +const CONSTANTS = symbol('CONSTANTS'); +const ARGS = symbol('ARGS'); +const PC = symbol('PC'); + +class CursorImpl { + constructor(element, nextSibling) { + this.element = element; + this.nextSibling = nextSibling; + } + +} +class ConcreteBounds { + constructor(parentNode, first, last) { + this.parentNode = parentNode; + this.first = first; + this.last = last; + } + + parentElement() { + return this.parentNode; + } + + firstNode() { + return this.first; + } + + lastNode() { + return this.last; + } + +} +class SingleNodeBounds { + constructor(parentNode, node) { + this.parentNode = parentNode; + this.node = node; + } + + parentElement() { + return this.parentNode; + } + + firstNode() { + return this.node; + } + + lastNode() { + return this.node; + } + +} +function move(bounds, reference) { + let parent = bounds.parentElement(); + let first = bounds.firstNode(); + let last = bounds.lastNode(); + let current = first; + + while (true) { + let next = current.nextSibling; + parent.insertBefore(current, reference); + + if (current === last) { + return next; + } + + current = next; + } +} +function clear(bounds) { + let parent = bounds.parentElement(); + let first = bounds.firstNode(); + let last = bounds.lastNode(); + let current = first; + + while (true) { + let next = current.nextSibling; + parent.removeChild(current); + + if (current === last) { + return next; + } + + current = next; + } +} + +function normalizeStringValue(value) { + if (isEmpty(value)) { + return ''; + } + + return String(value); +} +function shouldCoerce(value) { + return isString(value) || isEmpty(value) || typeof value === 'boolean' || typeof value === 'number'; +} +function isEmpty(value) { + return value === null || value === undefined || typeof value.toString !== 'function'; +} +function isSafeString(value) { + return typeof value === 'object' && value !== null && typeof value.toHTML === 'function'; +} +function isNode(value) { + return typeof value === 'object' && value !== null && typeof value.nodeType === 'number'; +} +function isFragment(value) { + return isNode(value) && value.nodeType === 11; +} +function isString(value) { + return typeof value === 'string'; +} + +/* + * @method normalizeProperty + * @param element {HTMLElement} + * @param slotName {String} + * @returns {Object} { name, type } + */ +function normalizeProperty(element, slotName) { + let type, normalized; + + if (slotName in element) { + normalized = slotName; + type = 'prop'; + } else { + let lower = slotName.toLowerCase(); + + if (lower in element) { + type = 'prop'; + normalized = lower; + } else { + type = 'attr'; + normalized = slotName; + } + } + + if (type === 'prop' && (normalized.toLowerCase() === 'style' || preferAttr(element.tagName, normalized))) { + type = 'attr'; + } + + return { + normalized, + type + }; +} +// * browser bug +// * strange spec outlier + +const ATTR_OVERRIDES = { + INPUT: { + form: true, + // Chrome 46.0.2464.0: 'autocorrect' in document.createElement('input') === false + // Safari 8.0.7: 'autocorrect' in document.createElement('input') === false + // Mobile Safari (iOS 8.4 simulator): 'autocorrect' in document.createElement('input') === true + autocorrect: true, + // Chrome 54.0.2840.98: 'list' in document.createElement('input') === true + // Safari 9.1.3: 'list' in document.createElement('input') === false + list: true + }, + // element.form is actually a legitimate readOnly property, that is to be + // mutated, but must be mutated by setAttribute... + SELECT: { + form: true + }, + OPTION: { + form: true + }, + TEXTAREA: { + form: true + }, + LABEL: { + form: true + }, + FIELDSET: { + form: true + }, + LEGEND: { + form: true + }, + OBJECT: { + form: true + }, + OUTPUT: { + form: true + }, + BUTTON: { + form: true + } +}; + +function preferAttr(tagName, propName) { + let tag = ATTR_OVERRIDES[tagName.toUpperCase()]; + return tag && tag[propName.toLowerCase()] || false; +} + +const badProtocols = ['javascript:', 'vbscript:']; +const badTags = ['A', 'BODY', 'LINK', 'IMG', 'IFRAME', 'BASE', 'FORM']; +const badTagsForDataURI = ['EMBED']; +const badAttributes = ['href', 'src', 'background', 'action']; +const badAttributesForDataURI = ['src']; + +function has(array, item) { + return array.indexOf(item) !== -1; +} + +function checkURI(tagName, attribute) { + return (tagName === null || has(badTags, tagName)) && has(badAttributes, attribute); +} + +function checkDataURI(tagName, attribute) { + if (tagName === null) return false; + return has(badTagsForDataURI, tagName) && has(badAttributesForDataURI, attribute); +} + +function requiresSanitization(tagName, attribute) { + return checkURI(tagName, attribute) || checkDataURI(tagName, attribute); +} +let protocolForUrl; + +if (typeof URL === 'object' && URL !== null && // this is super annoying, TS thinks that URL **must** be a function so `URL.parse` check +// thinks it is `never` without this `as unknown as any` +typeof URL.parse === 'function') { + // In Ember-land the `fastboot` package sets the `URL` global to `require('url')` + // ultimately, this should be changed (so that we can either rely on the natural `URL` global + // that exists) but for now we have to detect the specific `FastBoot` case first + // + // a future version of `fastboot` will detect if this legacy URL setup is required (by + // inspecting Ember version) and if new enough, it will avoid shadowing the `URL` global + // constructor with `require('url')`. + let nodeURL = URL; + + protocolForUrl = url => { + let protocol = null; + + if (typeof url === 'string') { + protocol = nodeURL.parse(url).protocol; + } + + return protocol === null ? ':' : protocol; + }; +} else if (typeof URL === 'function') { + protocolForUrl = _url => { + try { + let url = new URL(_url); + return url.protocol; + } catch (error) { + // any non-fully qualified url string will trigger an error (because there is no + // baseURI that we can provide; in that case we **know** that the protocol is + // "safe" because it isn't specifically one of the `badProtocols` listed above + // (and those protocols can never be the default baseURI) + return ':'; + } + }; +} else { + // fallback for IE11 support + let parsingNode = document.createElement('a'); + + protocolForUrl = url => { + parsingNode.href = url; + return parsingNode.protocol; + }; +} + +function sanitizeAttributeValue(element, attribute, value) { + let tagName = null; + + if (value === null || value === undefined) { + return value; + } + + if (isSafeString(value)) { + return value.toHTML(); + } + + if (!element) { + tagName = null; + } else { + tagName = element.tagName.toUpperCase(); + } + + let str = normalizeStringValue(value); + + if (checkURI(tagName, attribute)) { + let protocol = protocolForUrl(str); + + if (has(badProtocols, protocol)) { + return `unsafe:${str}`; + } + } + + if (checkDataURI(tagName, attribute)) { + return `unsafe:${str}`; + } + + return str; +} + +function dynamicAttribute(element, attr, namespace, isTrusting = false) { + let { + tagName, + namespaceURI + } = element; + let attribute = { + element, + name: attr, + namespace + }; + + if (DEBUG && attr === 'style' && !isTrusting) { + return new DebugStyleAttributeManager(attribute); + } + + if (namespaceURI === "http://www.w3.org/2000/svg" + /* SVG */ + ) { + return buildDynamicAttribute(tagName, attr, attribute); + } + + let { + type, + normalized + } = normalizeProperty(element, attr); + + if (type === 'attr') { + return buildDynamicAttribute(tagName, normalized, attribute); + } else { + return buildDynamicProperty(tagName, normalized, attribute); + } +} + +function buildDynamicAttribute(tagName, name, attribute) { + if (requiresSanitization(tagName, name)) { + return new SafeDynamicAttribute(attribute); + } else { + return new SimpleDynamicAttribute(attribute); + } +} + +function buildDynamicProperty(tagName, name, attribute) { + if (requiresSanitization(tagName, name)) { + return new SafeDynamicProperty(name, attribute); + } + + if (isUserInputValue(tagName, name)) { + return new InputValueDynamicAttribute(name, attribute); + } + + if (isOptionSelected(tagName, name)) { + return new OptionSelectedDynamicAttribute(name, attribute); + } + + return new DefaultDynamicProperty(name, attribute); +} + +class DynamicAttribute { + constructor(attribute) { + this.attribute = attribute; + } + +} +class SimpleDynamicAttribute extends DynamicAttribute { + set(dom, value, _env) { + let normalizedValue = normalizeValue(value); + + if (normalizedValue !== null) { + let { + name, + namespace + } = this.attribute; + + dom.__setAttribute(name, normalizedValue, namespace); + } + } + + update(value, _env) { + let normalizedValue = normalizeValue(value); + let { + element, + name + } = this.attribute; + + if (normalizedValue === null) { + element.removeAttribute(name); + } else { + element.setAttribute(name, normalizedValue); + } + } + +} +class DefaultDynamicProperty extends DynamicAttribute { + constructor(normalizedName, attribute) { + super(attribute); + this.normalizedName = normalizedName; + } + + set(dom, value, _env) { + if (value !== null && value !== undefined) { + this.value = value; + + dom.__setProperty(this.normalizedName, value); + } + } + + update(value, _env) { + let { + element + } = this.attribute; + + if (this.value !== value) { + element[this.normalizedName] = this.value = value; + + if (value === null || value === undefined) { + this.removeAttribute(); + } + } + } + + removeAttribute() { + // TODO this sucks but to preserve properties first and to meet current + // semantics we must do this. + let { + element, + namespace + } = this.attribute; + + if (namespace) { + element.removeAttributeNS(namespace, this.normalizedName); + } else { + element.removeAttribute(this.normalizedName); + } + } + +} +class SafeDynamicProperty extends DefaultDynamicProperty { + set(dom, value, env) { + let { + element, + name + } = this.attribute; + let sanitized = sanitizeAttributeValue(element, name, value); + super.set(dom, sanitized, env); + } + + update(value, env) { + let { + element, + name + } = this.attribute; + let sanitized = sanitizeAttributeValue(element, name, value); + super.update(sanitized, env); + } + +} +class SafeDynamicAttribute extends SimpleDynamicAttribute { + set(dom, value, env) { + let { + element, + name + } = this.attribute; + let sanitized = sanitizeAttributeValue(element, name, value); + super.set(dom, sanitized, env); + } + + update(value, env) { + let { + element, + name + } = this.attribute; + let sanitized = sanitizeAttributeValue(element, name, value); + super.update(sanitized, env); + } + +} +class InputValueDynamicAttribute extends DefaultDynamicProperty { + set(dom, value) { + dom.__setProperty('value', normalizeStringValue(value)); + } + + update(value) { + let input = this.attribute.element; + let currentValue = input.value; + let normalizedValue = normalizeStringValue(value); + + if (currentValue !== normalizedValue) { + input.value = normalizedValue; + } + } + +} +class OptionSelectedDynamicAttribute extends DefaultDynamicProperty { + set(dom, value) { + if (value !== null && value !== undefined && value !== false) { + dom.__setProperty('selected', true); + } + } + + update(value) { + let option = this.attribute.element; + + if (value) { + option.selected = true; + } else { + option.selected = false; + } + } + +} + +function isOptionSelected(tagName, attribute) { + return tagName === 'OPTION' && attribute === 'selected'; +} + +function isUserInputValue(tagName, attribute) { + return (tagName === 'INPUT' || tagName === 'TEXTAREA') && attribute === 'value'; +} + +function normalizeValue(value) { + if (value === false || value === undefined || value === null || typeof value.toString === 'undefined') { + return null; + } + + if (value === true) { + return ''; + } // onclick function etc in SSR + + + if (typeof value === 'function') { + return null; + } + + return String(value); +} + +let DebugStyleAttributeManager; + +if (DEBUG) { + DebugStyleAttributeManager = class extends SimpleDynamicAttribute { + set(dom, value, env) { + warnIfStyleNotTrusted(value); + super.set(dom, value, env); + } + + update(value, env) { + warnIfStyleNotTrusted(value); + super.update(value, env); + } + + }; +} + +var _a; + +class First { + constructor(node) { + this.node = node; + } + + firstNode() { + return this.node; + } + +} + +class Last { + constructor(node) { + this.node = node; + } + + lastNode() { + return this.node; + } + +} +const CURSOR_STACK = symbol('CURSOR_STACK'); +class NewElementBuilder { + constructor(env, parentNode, nextSibling) { + this.constructing = null; + this.operations = null; + this[_a] = new Stack(); + this.modifierStack = new Stack(); + this.blockStack = new Stack(); + this.pushElement(parentNode, nextSibling); + this.env = env; + this.dom = env.getAppendOperations(); + this.updateOperations = env.getDOM(); + } + + static forInitialRender(env, cursor) { + return new this(env, cursor.element, cursor.nextSibling).initialize(); + } + + static resume(env, block) { + let parentNode = block.parentElement(); + let nextSibling = block.reset(env); + let stack = new this(env, parentNode, nextSibling).initialize(); + stack.pushLiveBlock(block); + return stack; + } + + initialize() { + this.pushSimpleBlock(); + return this; + } + + debugBlocks() { + return this.blockStack.toArray(); + } + + get element() { + return this[CURSOR_STACK].current.element; + } + + get nextSibling() { + return this[CURSOR_STACK].current.nextSibling; + } + + get hasBlocks() { + return this.blockStack.size > 0; + } + + block() { + return this.blockStack.current; + } + + popElement() { + this[CURSOR_STACK].pop(); + this[CURSOR_STACK].current; + } + + pushSimpleBlock() { + return this.pushLiveBlock(new SimpleLiveBlock(this.element)); + } + + pushUpdatableBlock() { + return this.pushLiveBlock(new UpdatableBlockImpl(this.element)); + } + + pushBlockList(list) { + return this.pushLiveBlock(new LiveBlockList(this.element, list)); + } + + pushLiveBlock(block, isRemote = false) { + let current = this.blockStack.current; + + if (current !== null) { + if (!isRemote) { + current.didAppendBounds(block); + } + } + + this.__openBlock(); + + this.blockStack.push(block); + return block; + } + + popBlock() { + this.block().finalize(this); + + this.__closeBlock(); + + return this.blockStack.pop(); + } + + __openBlock() {} + + __closeBlock() {} // todo return seems unused + + + openElement(tag) { + let element = this.__openElement(tag); + + this.constructing = element; + return element; + } + + __openElement(tag) { + return this.dom.createElement(tag, this.element); + } + + flushElement(modifiers) { + let parent = this.element; + let element = this.constructing; + + this.__flushElement(parent, element); + + this.constructing = null; + this.operations = null; + this.pushModifiers(modifiers); + this.pushElement(element, null); + this.didOpenElement(element); + } + + __flushElement(parent, constructing) { + this.dom.insertBefore(parent, constructing, this.nextSibling); + } + + closeElement() { + this.willCloseElement(); + this.popElement(); + return this.popModifiers(); + } + + pushRemoteElement(element, guid, insertBefore) { + return this.__pushRemoteElement(element, guid, insertBefore); + } + + __pushRemoteElement(element, _guid, insertBefore) { + this.pushElement(element, insertBefore); + + if (insertBefore === undefined) { + while (element.lastChild) { + element.removeChild(element.lastChild); + } + } + + let block = new RemoteLiveBlock(element); + return this.pushLiveBlock(block, true); + } + + popRemoteElement() { + this.popBlock(); + this.popElement(); + } + + pushElement(element, nextSibling = null) { + this[CURSOR_STACK].push(new CursorImpl(element, nextSibling)); + } + + pushModifiers(modifiers) { + this.modifierStack.push(modifiers); + } + + popModifiers() { + return this.modifierStack.pop(); + } + + didAppendBounds(bounds) { + this.block().didAppendBounds(bounds); + return bounds; + } + + didAppendNode(node) { + this.block().didAppendNode(node); + return node; + } + + didOpenElement(element) { + this.block().openElement(element); + return element; + } + + willCloseElement() { + this.block().closeElement(); + } + + appendText(string) { + return this.didAppendNode(this.__appendText(string)); + } + + __appendText(text) { + let { + dom, + element, + nextSibling + } = this; + let node = dom.createTextNode(text); + dom.insertBefore(element, node, nextSibling); + return node; + } + + __appendNode(node) { + this.dom.insertBefore(this.element, node, this.nextSibling); + return node; + } + + __appendFragment(fragment) { + let first = fragment.firstChild; + + if (first) { + let ret = new ConcreteBounds(this.element, first, fragment.lastChild); + this.dom.insertBefore(this.element, fragment, this.nextSibling); + return ret; + } else { + return new SingleNodeBounds(this.element, this.__appendComment('')); + } + } + + __appendHTML(html) { + return this.dom.insertHTMLBefore(this.element, this.nextSibling, html); + } + + appendDynamicHTML(value) { + let bounds = this.trustedContent(value); + this.didAppendBounds(bounds); + } + + appendDynamicText(value) { + let node = this.untrustedContent(value); + this.didAppendNode(node); + return node; + } + + appendDynamicFragment(value) { + let bounds = this.__appendFragment(value); + + this.didAppendBounds(bounds); + } + + appendDynamicNode(value) { + let node = this.__appendNode(value); + + let bounds = new SingleNodeBounds(this.element, node); + this.didAppendBounds(bounds); + } + + trustedContent(value) { + return this.__appendHTML(value); + } + + untrustedContent(value) { + return this.__appendText(value); + } + + appendComment(string) { + return this.didAppendNode(this.__appendComment(string)); + } + + __appendComment(string) { + let { + dom, + element, + nextSibling + } = this; + let node = dom.createComment(string); + dom.insertBefore(element, node, nextSibling); + return node; + } + + __setAttribute(name, value, namespace) { + this.dom.setAttribute(this.constructing, name, value, namespace); + } + + __setProperty(name, value) { + this.constructing[name] = value; + } + + setStaticAttribute(name, value, namespace) { + this.__setAttribute(name, value, namespace); + } + + setDynamicAttribute(name, value, trusting, namespace) { + let element = this.constructing; + let attribute = dynamicAttribute(element, name, namespace, trusting); + attribute.set(this, value, this.env); + return attribute; + } + +} +_a = CURSOR_STACK; +class SimpleLiveBlock { + constructor(parent) { + this.parent = parent; + this.first = null; + this.last = null; + this.nesting = 0; + } + + parentElement() { + return this.parent; + } + + firstNode() { + let first = this.first; + return first.firstNode(); + } + + lastNode() { + let last = this.last; + return last.lastNode(); + } + + openElement(element) { + this.didAppendNode(element); + this.nesting++; + } + + closeElement() { + this.nesting--; + } + + didAppendNode(node) { + if (this.nesting !== 0) return; + + if (!this.first) { + this.first = new First(node); + } + + this.last = new Last(node); + } + + didAppendBounds(bounds) { + if (this.nesting !== 0) return; + + if (!this.first) { + this.first = bounds; + } + + this.last = bounds; + } + + finalize(stack) { + if (this.first === null) { + stack.appendComment(''); + } + } + +} +class RemoteLiveBlock extends SimpleLiveBlock { + constructor(parent) { + super(parent); + registerDestructor(this, () => { + // In general, you only need to clear the root of a hierarchy, and should never + // need to clear any child nodes. This is an important constraint that gives us + // a strong guarantee that clearing a subtree is a single DOM operation. + // + // Because remote blocks are not normally physically nested inside of the tree + // that they are logically nested inside, we manually clear remote blocks when + // a logical parent is cleared. + // + // HOWEVER, it is currently possible for a remote block to be physically nested + // inside of the block it is logically contained inside of. This happens when + // the remote block is appended to the end of the application's entire element. + // + // The problem with that scenario is that Glimmer believes that it owns more of + // the DOM than it actually does. The code is attempting to write past the end + // of the Glimmer-managed root, but Glimmer isn't aware of that. + // + // The correct solution to that problem is for Glimmer to be aware of the end + // of the bounds that it owns, and once we make that change, this check could + // be removed. + // + // For now, a more targeted fix is to check whether the node was already removed + // and avoid clearing the node if it was. In most cases this shouldn't happen, + // so this might hide bugs where the code clears nested nodes unnecessarily, + // so we should eventually try to do the correct fix. + if (this.parentElement() === this.firstNode().parentNode) { + clear(this); + } + }); + } + +} +class UpdatableBlockImpl extends SimpleLiveBlock { + reset() { + destroy(this); + let nextSibling = clear(this); + this.first = null; + this.last = null; + this.nesting = 0; + return nextSibling; + } + +} // FIXME: All the noops in here indicate a modelling problem + +class LiveBlockList { + constructor(parent, boundList) { + this.parent = parent; + this.boundList = boundList; + this.parent = parent; + this.boundList = boundList; + } + + parentElement() { + return this.parent; + } + + firstNode() { + let head = this.boundList[0]; + return head.firstNode(); + } + + lastNode() { + let boundList = this.boundList; + let tail = boundList[boundList.length - 1]; + return tail.lastNode(); + } + + openElement(_element) { + } + + closeElement() { + } + + didAppendNode(_node) { + } + + didAppendBounds(_bounds) {} + + finalize(_stack) { + } + +} +function clientBuilder(env, cursor) { + return NewElementBuilder.forInitialRender(env, cursor); +} + +class AppendOpcodes { + constructor() { + this.evaluateOpcode = fillNulls(104 + /* Size */ + ).slice(); + } + + add(name, evaluate, kind = 'syscall') { + this.evaluateOpcode[name] = { + syscall: kind !== 'machine', + evaluate + }; + } + + debugBefore(vm, opcode) { + let params = undefined; + let opName = undefined; + + let sp; + + return { + sp: sp, + pc: vm.fetchValue($pc), + name: opName, + params, + type: opcode.type, + isMachine: opcode.isMachine, + size: opcode.size, + state: undefined + }; + } + + debugAfter(vm, pre) { + } + + evaluate(vm, opcode, type) { + let operation = this.evaluateOpcode[type]; + + if (operation.syscall) { + operation.evaluate(vm, opcode); + } else { + operation.evaluate(vm[INNER_VM], opcode); + } + } + +} +const APPEND_OPCODES = new AppendOpcodes(); + +function createConcatRef(partsRefs) { + return createComputeRef(() => { + let parts = new Array(); + + for (let i = 0; i < partsRefs.length; i++) { + let value = valueForRef(partsRefs[i]); + + if (value !== null && value !== undefined) { + parts[i] = castToString(value); + } + } + + if (parts.length > 0) { + return parts.join(''); + } + + return null; + }); +} + +function castToString(value) { + if (typeof value.toString !== 'function') { + return ''; + } + + return String(value); +} + +const TYPE = symbol('TYPE'); +const INNER = symbol('INNER'); +const OWNER = symbol('OWNER'); +const ARGS$1 = symbol('ARGS'); +const RESOLVED = symbol('RESOLVED'); +const CURRIED_VALUES = new _WeakSet(); +function isCurriedValue(value) { + return CURRIED_VALUES.has(value); +} +function isCurriedType(value, type) { + return isCurriedValue(value) && value[TYPE] === type; +} +class CurriedValue { + /** @internal */ + constructor(type, inner, owner, args, resolved = false) { + CURRIED_VALUES.add(this); + this[TYPE] = type; + this[INNER] = inner; + this[OWNER] = owner; + this[ARGS$1] = args; + this[RESOLVED] = resolved; + } + +} +function resolveCurriedValue(curriedValue) { + let currentWrapper = curriedValue; + let positional; + let named; + let definition, owner, resolved; + + while (true) { + let { + [ARGS$1]: curriedArgs, + [INNER]: inner + } = currentWrapper; + + if (curriedArgs !== null) { + let { + named: curriedNamed, + positional: curriedPositional + } = curriedArgs; + + if (curriedPositional.length > 0) { + positional = positional === undefined ? curriedPositional : curriedPositional.concat(positional); + } + + if (named === undefined) { + named = []; + } + + named.unshift(curriedNamed); + } + + if (!isCurriedValue(inner)) { + // Save off the owner that this helper was curried with. Later on, + // we'll fetch the value of this register and set it as the owner on the + // new root scope. + definition = inner; + owner = currentWrapper[OWNER]; + resolved = currentWrapper[RESOLVED]; + break; + } + + currentWrapper = inner; + } + + return { + definition, + owner, + resolved, + positional, + named + }; +} +function curry(type, spec, owner, args, resolved = false) { + return new CurriedValue(type, spec, owner, args, resolved); +} + +function createCurryRef(type, inner, owner, args, resolver, isStrict) { + let lastValue, curriedDefinition; + return createComputeRef(() => { + let value = valueForRef(inner); + + if (value === lastValue) { + return curriedDefinition; + } + + if (isCurriedType(value, type)) { + curriedDefinition = args ? curry(type, value, owner, args) : args; + } else if (type === 0 + /* Component */ + && typeof value === 'string' && value) { + // Only components should enter this path, as helpers and modifiers do not + // support string based resolution + if (DEBUG) { + if (isStrict) { + throw new Error(`Attempted to resolve a dynamic component with a string definition, \`${value}\` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly.`); + } + + let resolvedDefinition = resolver.lookupComponent(value, owner); + + if (!resolvedDefinition) { + throw new Error(`Attempted to resolve \`${value}\`, which was expected to be a component, but nothing was found.`); + } + } + + curriedDefinition = curry(type, value, owner, args); + } else if (isObject(value)) { + curriedDefinition = curry(type, value, owner, args); + } else { + curriedDefinition = null; + } + + lastValue = value; + return curriedDefinition; + }); +} + +/* + The calling convention is: + + * 0-N block arguments at the bottom + * 0-N positional arguments next (left-to-right) + * 0-N named arguments next +*/ + +class VMArgumentsImpl { + constructor() { + this.stack = null; + this.positional = new PositionalArgumentsImpl(); + this.named = new NamedArgumentsImpl(); + this.blocks = new BlockArgumentsImpl(); + } + + empty(stack) { + let base = stack[REGISTERS][$sp] + 1; + this.named.empty(stack, base); + this.positional.empty(stack, base); + this.blocks.empty(stack, base); + return this; + } + + setup(stack, names, blockNames, positionalCount, atNames) { + this.stack = stack; + /* + | ... | blocks | positional | named | + | ... | b0 b1 | p0 p1 p2 p3 | n0 n1 | + index | ... | 4/5/6 7/8/9 | 10 11 12 13 | 14 15 | + ^ ^ ^ ^ + bbase pbase nbase sp + */ + + let named = this.named; + let namedCount = names.length; + let namedBase = stack[REGISTERS][$sp] - namedCount + 1; + named.setup(stack, namedBase, namedCount, names, atNames); + let positional = this.positional; + let positionalBase = namedBase - positionalCount; + positional.setup(stack, positionalBase, positionalCount); + let blocks = this.blocks; + let blocksCount = blockNames.length; + let blocksBase = positionalBase - blocksCount * 3; + blocks.setup(stack, blocksBase, blocksCount, blockNames); + } + + get base() { + return this.blocks.base; + } + + get length() { + return this.positional.length + this.named.length + this.blocks.length * 3; + } + + at(pos) { + return this.positional.at(pos); + } + + realloc(offset) { + let { + stack + } = this; + + if (offset > 0 && stack !== null) { + let { + positional, + named + } = this; + let newBase = positional.base + offset; + let length = positional.length + named.length; + + for (let i = length - 1; i >= 0; i--) { + stack.copy(i + positional.base, i + newBase); + } + + positional.base += offset; + named.base += offset; + stack[REGISTERS][$sp] += offset; + } + } + + capture() { + let positional = this.positional.length === 0 ? EMPTY_POSITIONAL : this.positional.capture(); + let named = this.named.length === 0 ? EMPTY_NAMED : this.named.capture(); + return { + named, + positional + }; + } + + clear() { + let { + stack, + length + } = this; + if (length > 0 && stack !== null) stack.pop(length); + } + +} +const EMPTY_REFERENCES = emptyArray(); +class PositionalArgumentsImpl { + constructor() { + this.base = 0; + this.length = 0; + this.stack = null; + this._references = null; + } + + empty(stack, base) { + this.stack = stack; + this.base = base; + this.length = 0; + this._references = EMPTY_REFERENCES; + } + + setup(stack, base, length) { + this.stack = stack; + this.base = base; + this.length = length; + + if (length === 0) { + this._references = EMPTY_REFERENCES; + } else { + this._references = null; + } + } + + at(position) { + let { + base, + length, + stack + } = this; + + if (position < 0 || position >= length) { + return UNDEFINED_REFERENCE; + } + + return stack.get(position, base); + } + + capture() { + return this.references; + } + + prepend(other) { + let additions = other.length; + + if (additions > 0) { + let { + base, + length, + stack + } = this; + this.base = base = base - additions; + this.length = length + additions; + + for (let i = 0; i < additions; i++) { + stack.set(other[i], i, base); + } + + this._references = null; + } + } + + get references() { + let references = this._references; + + if (!references) { + let { + stack, + base, + length + } = this; + references = this._references = stack.slice(base, base + length); + } + + return references; + } + +} +class NamedArgumentsImpl { + constructor() { + this.base = 0; + this.length = 0; + this._references = null; + this._names = EMPTY_STRING_ARRAY; + this._atNames = EMPTY_STRING_ARRAY; + } + + empty(stack, base) { + this.stack = stack; + this.base = base; + this.length = 0; + this._references = EMPTY_REFERENCES; + this._names = EMPTY_STRING_ARRAY; + this._atNames = EMPTY_STRING_ARRAY; + } + + setup(stack, base, length, names, atNames) { + this.stack = stack; + this.base = base; + this.length = length; + + if (length === 0) { + this._references = EMPTY_REFERENCES; + this._names = EMPTY_STRING_ARRAY; + this._atNames = EMPTY_STRING_ARRAY; + } else { + this._references = null; + + if (atNames) { + this._names = null; + this._atNames = names; + } else { + this._names = names; + this._atNames = null; + } + } + } + + get names() { + let names = this._names; + + if (!names) { + names = this._names = this._atNames.map(this.toSyntheticName); + } + + return names; + } + + get atNames() { + let atNames = this._atNames; + + if (!atNames) { + atNames = this._atNames = this._names.map(this.toAtName); + } + + return atNames; + } + + has(name) { + return this.names.indexOf(name) !== -1; + } + + get(name, atNames = false) { + let { + base, + stack + } = this; + let names = atNames ? this.atNames : this.names; + let idx = names.indexOf(name); + + if (idx === -1) { + return UNDEFINED_REFERENCE; + } + + let ref = stack.get(idx, base); + + if (DEBUG) { + return createDebugAliasRef(atNames ? name : `@${name}`, ref); + } else { + return ref; + } + } + + capture() { + let { + names, + references + } = this; + let map = dict(); + + for (let i = 0; i < names.length; i++) { + let name = names[i]; + + if (DEBUG) { + map[name] = createDebugAliasRef(`@${name}`, references[i]); + } else { + map[name] = references[i]; + } + } + + return map; + } + + merge(other) { + let keys = Object.keys(other); + + if (keys.length > 0) { + let { + names, + length, + stack + } = this; + let newNames = names.slice(); + + for (let i = 0; i < keys.length; i++) { + let name = keys[i]; + let idx = newNames.indexOf(name); + + if (idx === -1) { + length = newNames.push(name); + stack.push(other[name]); + } + } + + this.length = length; + this._references = null; + this._names = newNames; + this._atNames = null; + } + } + + get references() { + let references = this._references; + + if (!references) { + let { + base, + length, + stack + } = this; + references = this._references = stack.slice(base, base + length); + } + + return references; + } + + toSyntheticName(name) { + return name.slice(1); + } + + toAtName(name) { + return `@${name}`; + } + +} + +function toSymbolName(name) { + return `&${name}`; +} + +const EMPTY_BLOCK_VALUES = emptyArray(); +class BlockArgumentsImpl { + constructor() { + this.internalValues = null; + this._symbolNames = null; + this.internalTag = null; + this.names = EMPTY_STRING_ARRAY; + this.length = 0; + this.base = 0; + } + + empty(stack, base) { + this.stack = stack; + this.names = EMPTY_STRING_ARRAY; + this.base = base; + this.length = 0; + this._symbolNames = null; + this.internalTag = CONSTANT_TAG; + this.internalValues = EMPTY_BLOCK_VALUES; + } + + setup(stack, base, length, names) { + this.stack = stack; + this.names = names; + this.base = base; + this.length = length; + this._symbolNames = null; + + if (length === 0) { + this.internalTag = CONSTANT_TAG; + this.internalValues = EMPTY_BLOCK_VALUES; + } else { + this.internalTag = null; + this.internalValues = null; + } + } + + get values() { + let values = this.internalValues; + + if (!values) { + let { + base, + length, + stack + } = this; + values = this.internalValues = stack.slice(base, base + length * 3); + } + + return values; + } + + has(name) { + return this.names.indexOf(name) !== -1; + } + + get(name) { + let idx = this.names.indexOf(name); + + if (idx === -1) { + return null; + } + + let { + base, + stack + } = this; + let table = stack.get(idx * 3, base); + let scope = stack.get(idx * 3 + 1, base); + let handle = stack.get(idx * 3 + 2, base); + return handle === null ? null : [handle, scope, table]; + } + + capture() { + return new CapturedBlockArgumentsImpl(this.names, this.values); + } + + get symbolNames() { + let symbolNames = this._symbolNames; + + if (symbolNames === null) { + symbolNames = this._symbolNames = this.names.map(toSymbolName); + } + + return symbolNames; + } + +} + +class CapturedBlockArgumentsImpl { + constructor(names, values) { + this.names = names; + this.values = values; + this.length = names.length; + } + + has(name) { + return this.names.indexOf(name) !== -1; + } + + get(name) { + let idx = this.names.indexOf(name); + if (idx === -1) return null; + return [this.values[idx * 3 + 2], this.values[idx * 3 + 1], this.values[idx * 3]]; + } + +} + +function createCapturedArgs(named, positional) { + return { + named, + positional + }; +} +function reifyNamed$1(named) { + let reified = dict(); + + for (let key in named) { + reified[key] = valueForRef(named[key]); + } + + return reified; +} +function reifyPositional$1(positional) { + return positional.map(valueForRef); +} +function reifyArgs(args) { + return { + named: reifyNamed$1(args.named), + positional: reifyPositional$1(args.positional) + }; +} +const EMPTY_NAMED = Object.freeze(Object.create(null)); +const EMPTY_POSITIONAL = EMPTY_REFERENCES; +const EMPTY_ARGS = createCapturedArgs(EMPTY_NAMED, EMPTY_POSITIONAL); + +APPEND_OPCODES.add(77 +/* Curry */ +, (vm, { + op1: type, + op2: _isStrict +}) => { + let stack = vm.stack; + let definition = stack.pop(); + let capturedArgs = stack.pop(); + let owner = vm.getOwner(); + let resolver = vm.runtime.resolver; + let isStrict = false; + + if (DEBUG) { + // strict check only happens in DEBUG builds, no reason to load it otherwise + isStrict = vm[CONSTANTS].getValue(decodeHandle(_isStrict)); + } + + vm.loadValue($v0, createCurryRef(type, definition, owner, capturedArgs, resolver, isStrict)); +}); +APPEND_OPCODES.add(107 +/* DynamicHelper */ +, vm => { + let stack = vm.stack; + let ref = stack.pop(); + let args = stack.pop().capture(); + let helperRef; + let initialOwner = vm.getOwner(); + let helperInstanceRef = createComputeRef(() => { + if (helperRef !== undefined) { + destroy(helperRef); + } + + let definition = valueForRef(ref); + + if (isCurriedType(definition, 1 + /* Helper */ + )) { + let { + definition: resolvedDef, + owner, + positional, + named + } = resolveCurriedValue(definition); + let helper = resolveHelper(vm[CONSTANTS], resolvedDef, ref); + + if (named !== undefined) { + args.named = assign({}, ...named, args.named); + } + + if (positional !== undefined) { + args.positional = positional.concat(args.positional); + } + + helperRef = helper(args, owner); + associateDestroyableChild(helperInstanceRef, helperRef); + } else if (isObject(definition)) { + let helper = resolveHelper(vm[CONSTANTS], definition, ref); + helperRef = helper(args, initialOwner); + + if (_hasDestroyableChildren(helperRef)) { + associateDestroyableChild(helperInstanceRef, helperRef); + } + } else { + helperRef = UNDEFINED_REFERENCE; + } + }); + let helperValueRef = createComputeRef(() => { + valueForRef(helperInstanceRef); + return valueForRef(helperRef); + }); + vm.associateDestroyable(helperInstanceRef); + vm.loadValue($v0, helperValueRef); +}); + +function resolveHelper(constants, definition, ref) { + let handle = constants.helper(definition, null, true); + + if (DEBUG && handle === null) { + throw new Error(`Expected a dynamic helper definition, but received an object or function that did not have a helper manager associated with it. The dynamic invocation was \`{{${ref.debugLabel}}}\` or \`(${ref.debugLabel})\`, and the incorrect definition is the value at the path \`${ref.debugLabel}\`, which was: ${debugToString(definition)}`); + } + + return constants.getValue(handle); +} + +APPEND_OPCODES.add(16 +/* Helper */ +, (vm, { + op1: handle +}) => { + let stack = vm.stack; + let helper = vm[CONSTANTS].getValue(handle); + let args = stack.pop(); + let value = helper(args.capture(), vm.getOwner(), vm.dynamicScope()); + + if (_hasDestroyableChildren(value)) { + vm.associateDestroyable(value); + } + + vm.loadValue($v0, value); +}); +APPEND_OPCODES.add(21 +/* GetVariable */ +, (vm, { + op1: symbol$$1 +}) => { + let expr = vm.referenceForSymbol(symbol$$1); + vm.stack.push(expr); +}); +APPEND_OPCODES.add(19 +/* SetVariable */ +, (vm, { + op1: symbol$$1 +}) => { + let expr = vm.stack.pop(); + vm.scope().bindSymbol(symbol$$1, expr); +}); +APPEND_OPCODES.add(20 +/* SetBlock */ +, (vm, { + op1: symbol$$1 +}) => { + let handle = vm.stack.pop(); + let scope = vm.stack.pop(); + let table = vm.stack.pop(); + vm.scope().bindBlock(symbol$$1, [handle, scope, table]); +}); +APPEND_OPCODES.add(102 +/* ResolveMaybeLocal */ +, (vm, { + op1: _name +}) => { + let name = vm[CONSTANTS].getValue(_name); + let locals = vm.scope().getPartialMap(); + let ref = locals[name]; + + if (ref === undefined) { + ref = childRefFor(vm.getSelf(), name); + } + + vm.stack.push(ref); +}); +APPEND_OPCODES.add(37 +/* RootScope */ +, (vm, { + op1: symbols +}) => { + vm.pushRootScope(symbols, vm.getOwner()); +}); +APPEND_OPCODES.add(22 +/* GetProperty */ +, (vm, { + op1: _key +}) => { + let key = vm[CONSTANTS].getValue(_key); + let expr = vm.stack.pop(); + vm.stack.push(childRefFor(expr, key)); +}); +APPEND_OPCODES.add(23 +/* GetBlock */ +, (vm, { + op1: _block +}) => { + let { + stack + } = vm; + let block = vm.scope().getBlock(_block); + stack.push(block); +}); +APPEND_OPCODES.add(24 +/* SpreadBlock */ +, vm => { + let { + stack + } = vm; + let block = stack.pop(); + + if (block && !isUndefinedReference(block)) { + let [handleOrCompilable, scope, table] = block; + stack.push(table); + stack.push(scope); + stack.push(handleOrCompilable); + } else { + stack.push(null); + stack.push(null); + stack.push(null); + } +}); + +function isUndefinedReference(input) { + return input === UNDEFINED_REFERENCE; +} + +APPEND_OPCODES.add(25 +/* HasBlock */ +, vm => { + let { + stack + } = vm; + let block = stack.pop(); + + if (block && !isUndefinedReference(block)) { + stack.push(TRUE_REFERENCE); + } else { + stack.push(FALSE_REFERENCE); + } +}); +APPEND_OPCODES.add(26 +/* HasBlockParams */ +, vm => { + // FIXME(mmun): should only need to push the symbol table + let block = vm.stack.pop(); + let scope = vm.stack.pop(); + let table = vm.stack.pop(); + let hasBlockParams = table && table.parameters.length; + vm.stack.push(hasBlockParams ? TRUE_REFERENCE : FALSE_REFERENCE); +}); +APPEND_OPCODES.add(27 +/* Concat */ +, (vm, { + op1: count +}) => { + let out = new Array(count); + + for (let i = count; i > 0; i--) { + let offset = i - 1; + out[offset] = vm.stack.pop(); + } + + vm.stack.push(createConcatRef(out)); +}); +APPEND_OPCODES.add(109 +/* IfInline */ +, vm => { + let condition = vm.stack.pop(); + let truthy = vm.stack.pop(); + let falsy = vm.stack.pop(); + vm.stack.push(createComputeRef(() => { + if (toBool(valueForRef(condition)) === true) { + return valueForRef(truthy); + } else { + return valueForRef(falsy); + } + })); +}); +APPEND_OPCODES.add(110 +/* Not */ +, vm => { + let ref = vm.stack.pop(); + vm.stack.push(createComputeRef(() => { + return !toBool(valueForRef(ref)); + })); +}); +APPEND_OPCODES.add(111 +/* GetDynamicVar */ +, vm => { + let scope = vm.dynamicScope(); + let stack = vm.stack; + let nameRef = stack.pop(); + stack.push(createComputeRef(() => { + let name = String(valueForRef(nameRef)); + return valueForRef(scope.get(name)); + })); +}); +APPEND_OPCODES.add(112 +/* Log */ +, vm => { + let { + positional + } = vm.stack.pop().capture(); + vm.loadValue($v0, createComputeRef(() => { + // eslint-disable-next-line no-console + console.log(...reifyPositional$1(positional)); + })); +}); + +function resolveComponent(resolver, constants, name, owner) { + let definition = resolver.lookupComponent(name, owner); + + if (DEBUG && !definition) { + throw new Error(`Attempted to resolve \`${name}\`, which was expected to be a component, but nothing was found.`); + } + + return constants.resolvedComponent(definition, name); +} + +/** @internal */ +function hasCustomDebugRenderTreeLifecycle(manager) { + return 'getDebugCustomRenderTree' in manager; +} + +function createClassListRef(list) { + return createComputeRef(() => { + let ret = []; + + for (let i = 0; i < list.length; i++) { + let ref = list[i]; + let value = normalizeStringValue(typeof ref === 'string' ? ref : valueForRef(list[i])); + if (value) ret.push(value); + } + + return ret.length === 0 ? null : ret.join(' '); + }); +} + +APPEND_OPCODES.add(39 +/* ChildScope */ +, vm => vm.pushChildScope()); +APPEND_OPCODES.add(40 +/* PopScope */ +, vm => vm.popScope()); +APPEND_OPCODES.add(59 +/* PushDynamicScope */ +, vm => vm.pushDynamicScope()); +APPEND_OPCODES.add(60 +/* PopDynamicScope */ +, vm => vm.popDynamicScope()); +APPEND_OPCODES.add(28 +/* Constant */ +, (vm, { + op1: other +}) => { + vm.stack.push(vm[CONSTANTS].getValue(decodeHandle(other))); +}); +APPEND_OPCODES.add(29 +/* ConstantReference */ +, (vm, { + op1: other +}) => { + vm.stack.push(createConstRef(vm[CONSTANTS].getValue(decodeHandle(other)), false)); +}); +APPEND_OPCODES.add(30 +/* Primitive */ +, (vm, { + op1: primitive +}) => { + let stack = vm.stack; + + if (isHandle(primitive)) { + // it is a handle which does not already exist on the stack + let value = vm[CONSTANTS].getValue(decodeHandle(primitive)); + stack.push(value); + } else { + // is already an encoded immediate or primitive handle + stack.push(decodeImmediate(primitive)); + } +}); +APPEND_OPCODES.add(31 +/* PrimitiveReference */ +, vm => { + let stack = vm.stack; + let value = stack.pop(); + let ref; + + if (value === undefined) { + ref = UNDEFINED_REFERENCE; + } else if (value === null) { + ref = NULL_REFERENCE; + } else if (value === true) { + ref = TRUE_REFERENCE; + } else if (value === false) { + ref = FALSE_REFERENCE; + } else { + ref = createPrimitiveRef(value); + } + + stack.push(ref); +}); +APPEND_OPCODES.add(33 +/* Dup */ +, (vm, { + op1: register, + op2: offset +}) => { + let position = vm.fetchValue(register) - offset; + vm.stack.dup(position); +}); +APPEND_OPCODES.add(34 +/* Pop */ +, (vm, { + op1: count +}) => { + vm.stack.pop(count); +}); +APPEND_OPCODES.add(35 +/* Load */ +, (vm, { + op1: register +}) => { + vm.load(register); +}); +APPEND_OPCODES.add(36 +/* Fetch */ +, (vm, { + op1: register +}) => { + vm.fetch(register); +}); +APPEND_OPCODES.add(58 +/* BindDynamicScope */ +, (vm, { + op1: _names +}) => { + let names = vm[CONSTANTS].getArray(_names); + vm.bindDynamicScope(names); +}); +APPEND_OPCODES.add(69 +/* Enter */ +, (vm, { + op1: args +}) => { + vm.enter(args); +}); +APPEND_OPCODES.add(70 +/* Exit */ +, vm => { + vm.exit(); +}); +APPEND_OPCODES.add(63 +/* PushSymbolTable */ +, (vm, { + op1: _table +}) => { + let stack = vm.stack; + stack.push(vm[CONSTANTS].getValue(_table)); +}); +APPEND_OPCODES.add(62 +/* PushBlockScope */ +, vm => { + let stack = vm.stack; + stack.push(vm.scope()); +}); +APPEND_OPCODES.add(61 +/* CompileBlock */ +, vm => { + let stack = vm.stack; + let block = stack.pop(); + + if (block) { + stack.push(vm.compile(block)); + } else { + stack.push(null); + } +}); +APPEND_OPCODES.add(64 +/* InvokeYield */ +, vm => { + let { + stack + } = vm; + let handle = stack.pop(); + let scope = stack.pop(); + let table = stack.pop(); + let args = stack.pop(); + + if (table === null) { + // To balance the pop{Frame,Scope} + vm.pushFrame(); + vm.pushScope(scope !== null && scope !== void 0 ? scope : vm.scope()); + return; + } + + let invokingScope = scope; // If necessary, create a child scope + + { + let locals = table.parameters; + let localsCount = locals.length; + + if (localsCount > 0) { + invokingScope = invokingScope.child(); + + for (let i = 0; i < localsCount; i++) { + invokingScope.bindSymbol(locals[i], args.at(i)); + } + } + } + vm.pushFrame(); + vm.pushScope(invokingScope); + vm.call(handle); +}); +APPEND_OPCODES.add(65 +/* JumpIf */ +, (vm, { + op1: target +}) => { + let reference = vm.stack.pop(); + let value = Boolean(valueForRef(reference)); + + if (isConstRef(reference)) { + if (value === true) { + vm.goto(target); + } + } else { + if (value === true) { + vm.goto(target); + } + + vm.updateWith(new Assert(reference)); + } +}); +APPEND_OPCODES.add(66 +/* JumpUnless */ +, (vm, { + op1: target +}) => { + let reference = vm.stack.pop(); + let value = Boolean(valueForRef(reference)); + + if (isConstRef(reference)) { + if (value === false) { + vm.goto(target); + } + } else { + if (value === false) { + vm.goto(target); + } + + vm.updateWith(new Assert(reference)); + } +}); +APPEND_OPCODES.add(67 +/* JumpEq */ +, (vm, { + op1: target, + op2: comparison +}) => { + let other = vm.stack.peek(); + + if (other === comparison) { + vm.goto(target); + } +}); +APPEND_OPCODES.add(68 +/* AssertSame */ +, vm => { + let reference = vm.stack.peek(); + + if (isConstRef(reference) === false) { + vm.updateWith(new Assert(reference)); + } +}); +APPEND_OPCODES.add(71 +/* ToBoolean */ +, vm => { + let { + stack + } = vm; + let valueRef = stack.pop(); + stack.push(createComputeRef(() => toBool(valueForRef(valueRef)))); +}); +class Assert { + constructor(ref) { + this.ref = ref; + this.last = valueForRef(ref); + } + + evaluate(vm) { + let { + last, + ref + } = this; + let current = valueForRef(ref); + + if (last !== current) { + vm.throw(); + } + } + +} +class AssertFilter { + constructor(ref, filter) { + this.ref = ref; + this.filter = filter; + this.last = filter(valueForRef(ref)); + } + + evaluate(vm) { + let { + last, + ref, + filter + } = this; + let current = filter(valueForRef(ref)); + + if (last !== current) { + vm.throw(); + } + } + +} +class JumpIfNotModifiedOpcode { + constructor() { + this.tag = CONSTANT_TAG; + this.lastRevision = INITIAL; + } + + finalize(tag, target) { + this.target = target; + this.didModify(tag); + } + + evaluate(vm) { + let { + tag, + target, + lastRevision + } = this; + + if (!vm.alwaysRevalidate && validateTag(tag, lastRevision)) { + consumeTag(tag); + vm.goto(target); + } + } + + didModify(tag) { + this.tag = tag; + this.lastRevision = valueForTag(this.tag); + consumeTag(tag); + } + +} +class BeginTrackFrameOpcode { + constructor(debugLabel) { + this.debugLabel = debugLabel; + } + + evaluate() { + beginTrackFrame(this.debugLabel); + } + +} +class EndTrackFrameOpcode { + constructor(target) { + this.target = target; + } + + evaluate() { + let tag = endTrackFrame(); + this.target.didModify(tag); + } + +} + +APPEND_OPCODES.add(41 +/* Text */ +, (vm, { + op1: text +}) => { + vm.elements().appendText(vm[CONSTANTS].getValue(text)); +}); +APPEND_OPCODES.add(42 +/* Comment */ +, (vm, { + op1: text +}) => { + vm.elements().appendComment(vm[CONSTANTS].getValue(text)); +}); +APPEND_OPCODES.add(48 +/* OpenElement */ +, (vm, { + op1: tag +}) => { + vm.elements().openElement(vm[CONSTANTS].getValue(tag)); +}); +APPEND_OPCODES.add(49 +/* OpenDynamicElement */ +, vm => { + let tagName = valueForRef(vm.stack.pop()); + vm.elements().openElement(tagName); +}); +APPEND_OPCODES.add(50 +/* PushRemoteElement */ +, vm => { + let elementRef = vm.stack.pop(); + let insertBeforeRef = vm.stack.pop(); + let guidRef = vm.stack.pop(); + let element = valueForRef(elementRef); + let insertBefore = valueForRef(insertBeforeRef); + let guid = valueForRef(guidRef); + + if (!isConstRef(elementRef)) { + vm.updateWith(new Assert(elementRef)); + } + + if (insertBefore !== undefined && !isConstRef(insertBeforeRef)) { + vm.updateWith(new Assert(insertBeforeRef)); + } + + let block = vm.elements().pushRemoteElement(element, guid, insertBefore); + if (block) vm.associateDestroyable(block); +}); +APPEND_OPCODES.add(56 +/* PopRemoteElement */ +, vm => { + vm.elements().popRemoteElement(); +}); +APPEND_OPCODES.add(54 +/* FlushElement */ +, vm => { + let operations = vm.fetchValue($t0); + let modifiers = null; + + if (operations) { + modifiers = operations.flush(vm); + vm.loadValue($t0, null); + } + + vm.elements().flushElement(modifiers); +}); +APPEND_OPCODES.add(55 +/* CloseElement */ +, vm => { + let modifiers = vm.elements().closeElement(); + + if (modifiers) { + modifiers.forEach(modifier => { + vm.env.scheduleInstallModifier(modifier); + let { + manager, + state + } = modifier; + let d = manager.getDestroyable(state); + + if (d) { + vm.associateDestroyable(d); + } + }); + } +}); +APPEND_OPCODES.add(57 +/* Modifier */ +, (vm, { + op1: handle +}) => { + if (vm.env.isInteractive === false) { + return; + } + + let owner = vm.getOwner(); + let args = vm.stack.pop(); + let definition = vm[CONSTANTS].getValue(handle); + let { + manager + } = definition; + let { + constructing + } = vm.elements(); + let state = manager.create(owner, constructing, definition.state, args.capture()); + let instance = { + manager, + state, + definition + }; + let operations = vm.fetchValue($t0); + operations.addModifier(instance); + let tag = manager.getTag(state); + + if (tag !== null) { + consumeTag(tag); + return vm.updateWith(new UpdateModifierOpcode(tag, instance)); + } +}); +APPEND_OPCODES.add(108 +/* DynamicModifier */ +, vm => { + if (vm.env.isInteractive === false) { + return; + } + + let { + stack, + [CONSTANTS]: constants + } = vm; + let ref = stack.pop(); + let args = stack.pop().capture(); + let { + constructing + } = vm.elements(); + let initialOwner = vm.getOwner(); + let instanceRef = createComputeRef(() => { + let value = valueForRef(ref); + let owner; + + if (!isObject(value)) { + return; + } + + let hostDefinition; + + if (isCurriedType(value, 2 + /* Modifier */ + )) { + let { + definition: resolvedDefinition, + owner: curriedOwner, + positional, + named + } = resolveCurriedValue(value); + hostDefinition = resolvedDefinition; + owner = curriedOwner; + + if (positional !== undefined) { + args.positional = positional.concat(args.positional); + } + + if (named !== undefined) { + args.named = assign({}, ...named, args.named); + } + } else { + hostDefinition = value; + owner = initialOwner; + } + + let handle = constants.modifier(hostDefinition, null, true); + + if (DEBUG && handle === null) { + throw new Error(`Expected a dynamic modifier definition, but received an object or function that did not have a modifier manager associated with it. The dynamic invocation was \`{{${ref.debugLabel}}}\`, and the incorrect definition is the value at the path \`${ref.debugLabel}\`, which was: ${debugToString(hostDefinition)}`); + } + + let definition = constants.getValue(handle); + let { + manager + } = definition; + let state = manager.create(owner, constructing, definition.state, args); + return { + manager, + state, + definition + }; + }); + let instance = valueForRef(instanceRef); + let tag = null; + + if (instance !== undefined) { + let operations = vm.fetchValue($t0); + operations.addModifier(instance); + tag = instance.manager.getTag(instance.state); + + if (tag !== null) { + consumeTag(tag); + } + } + + if (!isConstRef(ref) || tag) { + return vm.updateWith(new UpdateDynamicModifierOpcode(tag, instance, instanceRef)); + } +}); +class UpdateModifierOpcode { + constructor(tag, modifier) { + this.tag = tag; + this.modifier = modifier; + this.lastUpdated = valueForTag(tag); + } + + evaluate(vm) { + let { + modifier, + tag, + lastUpdated + } = this; + consumeTag(tag); + + if (!validateTag(tag, lastUpdated)) { + vm.env.scheduleUpdateModifier(modifier); + this.lastUpdated = valueForTag(tag); + } + } + +} +class UpdateDynamicModifierOpcode { + constructor(tag, instance, instanceRef) { + this.tag = tag; + this.instance = instance; + this.instanceRef = instanceRef; + this.lastUpdated = valueForTag(tag !== null && tag !== void 0 ? tag : CURRENT_TAG); + } + + evaluate(vm) { + let { + tag, + lastUpdated, + instance, + instanceRef + } = this; + let newInstance = valueForRef(instanceRef); + + if (newInstance !== instance) { + if (instance !== undefined) { + let destroyable = instance.manager.getDestroyable(instance.state); + + if (destroyable !== null) { + destroy(destroyable); + } + } + + if (newInstance !== undefined) { + let { + manager, + state + } = newInstance; + let destroyable = manager.getDestroyable(state); + + if (destroyable !== null) { + associateDestroyableChild(this, destroyable); + } + + tag = manager.getTag(state); + + if (tag !== null) { + this.lastUpdated = valueForTag(tag); + } + + this.tag = tag; + vm.env.scheduleInstallModifier(newInstance); + } + + this.instance = newInstance; + } else if (tag !== null && !validateTag(tag, lastUpdated)) { + vm.env.scheduleUpdateModifier(instance); + this.lastUpdated = valueForTag(tag); + } + + if (tag !== null) { + consumeTag(tag); + } + } + +} +APPEND_OPCODES.add(51 +/* StaticAttr */ +, (vm, { + op1: _name, + op2: _value, + op3: _namespace +}) => { + let name = vm[CONSTANTS].getValue(_name); + let value = vm[CONSTANTS].getValue(_value); + let namespace = _namespace ? vm[CONSTANTS].getValue(_namespace) : null; + vm.elements().setStaticAttribute(name, value, namespace); +}); +APPEND_OPCODES.add(52 +/* DynamicAttr */ +, (vm, { + op1: _name, + op2: _trusting, + op3: _namespace +}) => { + let name = vm[CONSTANTS].getValue(_name); + let trusting = vm[CONSTANTS].getValue(_trusting); + let reference = vm.stack.pop(); + let value = valueForRef(reference); + let namespace = _namespace ? vm[CONSTANTS].getValue(_namespace) : null; + let attribute = vm.elements().setDynamicAttribute(name, value, trusting, namespace); + + if (!isConstRef(reference)) { + vm.updateWith(new UpdateDynamicAttributeOpcode(reference, attribute, vm.env)); + } +}); +class UpdateDynamicAttributeOpcode { + constructor(reference, attribute, env) { + let initialized = false; + this.updateRef = createComputeRef(() => { + let value = valueForRef(reference); + + if (initialized === true) { + attribute.update(value, env); + } else { + initialized = true; + } + }); + valueForRef(this.updateRef); + } + + evaluate() { + valueForRef(this.updateRef); + } + +} + +APPEND_OPCODES.add(78 +/* PushComponentDefinition */ +, (vm, { + op1: handle +}) => { + let definition = vm[CONSTANTS].getValue(handle); + let { + manager, + capabilities + } = definition; + let instance = { + definition, + manager, + capabilities, + state: null, + handle: null, + table: null, + lookup: null + }; + vm.stack.push(instance); +}); +APPEND_OPCODES.add(80 +/* ResolveDynamicComponent */ +, (vm, { + op1: _isStrict +}) => { + let stack = vm.stack; + let component = valueForRef(stack.pop()); + let constants = vm[CONSTANTS]; + let owner = vm.getOwner(); + let isStrict = constants.getValue(_isStrict); + vm.loadValue($t1, null); // Clear the temp register + + let definition; + + if (typeof component === 'string') { + if (DEBUG && isStrict) { + throw new Error(`Attempted to resolve a dynamic component with a string definition, \`${component}\` in a strict mode template. In strict mode, using strings to resolve component definitions is prohibited. You can instead import the component definition and use it directly.`); + } + + let resolvedDefinition = resolveComponent(vm.runtime.resolver, constants, component, owner); + definition = resolvedDefinition; + } else if (isCurriedValue(component)) { + definition = component; + } else { + definition = constants.component(component, owner); + } + + stack.push(definition); +}); +APPEND_OPCODES.add(81 +/* ResolveCurriedComponent */ +, vm => { + let stack = vm.stack; + let ref = stack.pop(); + let value = valueForRef(ref); + let constants = vm[CONSTANTS]; + let definition; + + if (DEBUG && !(typeof value === 'function' || typeof value === 'object' && value !== null)) { + throw new Error(`Expected a component definition, but received ${value}. You may have accidentally done <${ref.debugLabel}>, where "${ref.debugLabel}" was a string instead of a curried component definition. You must either use the component definition directly, or use the {{component}} helper to create a curried component definition when invoking dynamically.`); + } + + if (isCurriedValue(value)) { + definition = value; + } else { + definition = constants.component(value, vm.getOwner(), true); + + if (DEBUG && definition === null) { + throw new Error(`Expected a dynamic component definition, but received an object or function that did not have a component manager associated with it. The dynamic invocation was \`<${ref.debugLabel}>\` or \`{{${ref.debugLabel}}}\`, and the incorrect definition is the value at the path \`${ref.debugLabel}\`, which was: ${debugToString(value)}`); + } + } + + stack.push(definition); +}); +APPEND_OPCODES.add(79 +/* PushDynamicComponentInstance */ +, vm => { + let { + stack + } = vm; + let definition = stack.pop(); + let capabilities, manager; + + if (isCurriedValue(definition)) { + manager = capabilities = null; + } else { + manager = definition.manager; + capabilities = definition.capabilities; + } + + stack.push({ + definition, + capabilities, + manager, + state: null, + handle: null, + table: null + }); +}); +APPEND_OPCODES.add(82 +/* PushArgs */ +, (vm, { + op1: _names, + op2: _blockNames, + op3: flags +}) => { + let stack = vm.stack; + let names = vm[CONSTANTS].getArray(_names); + let positionalCount = flags >> 4; + let atNames = flags & 0b1000; + let blockNames = flags & 0b0111 ? vm[CONSTANTS].getArray(_blockNames) : EMPTY_STRING_ARRAY; + vm[ARGS].setup(stack, names, blockNames, positionalCount, !!atNames); + stack.push(vm[ARGS]); +}); +APPEND_OPCODES.add(83 +/* PushEmptyArgs */ +, vm => { + let { + stack + } = vm; + stack.push(vm[ARGS].empty(stack)); +}); +APPEND_OPCODES.add(86 +/* CaptureArgs */ +, vm => { + let stack = vm.stack; + let args = stack.pop(); + let capturedArgs = args.capture(); + stack.push(capturedArgs); +}); +APPEND_OPCODES.add(85 +/* PrepareArgs */ +, (vm, { + op1: _state +}) => { + let stack = vm.stack; + let instance = vm.fetchValue(_state); + let args = stack.pop(); + let { + definition + } = instance; + + if (isCurriedType(definition, 0 + /* Component */ + )) { + let constants = vm[CONSTANTS]; + let { + definition: resolvedDefinition, + owner, + resolved, + positional, + named + } = resolveCurriedValue(definition); + + if (resolved === true) { + definition = resolvedDefinition; + } else if (typeof resolvedDefinition === 'string') { + let resolvedValue = vm.runtime.resolver.lookupComponent(resolvedDefinition, owner); + definition = constants.resolvedComponent(resolvedValue, resolvedDefinition); + } else { + definition = constants.component(resolvedDefinition, owner); + } + + if (named !== undefined) { + args.named.merge(assign({}, ...named)); + } + + if (positional !== undefined) { + args.realloc(positional.length); + args.positional.prepend(positional); + } + + let { + manager + } = definition; + instance.definition = definition; + instance.manager = manager; + instance.capabilities = definition.capabilities; // Save off the owner that this component was curried with. Later on, + // we'll fetch the value of this register and set it as the owner on the + // new root scope. + + vm.loadValue($t1, owner); + } + + let { + manager, + state + } = definition; + let capabilities = instance.capabilities; + + if (!managerHasCapability(manager, capabilities, 4 + /* PrepareArgs */ + )) { + stack.push(args); + return; + } + + let blocks = args.blocks.values; + let blockNames = args.blocks.names; + let preparedArgs = manager.prepareArgs(state, args); + + if (preparedArgs) { + args.clear(); + + for (let i = 0; i < blocks.length; i++) { + stack.push(blocks[i]); + } + + let { + positional, + named + } = preparedArgs; + let positionalCount = positional.length; + + for (let i = 0; i < positionalCount; i++) { + stack.push(positional[i]); + } + + let names = Object.keys(named); + + for (let i = 0; i < names.length; i++) { + stack.push(named[names[i]]); + } + + args.setup(stack, names, blockNames, positionalCount, false); + } + + stack.push(args); +}); +APPEND_OPCODES.add(87 +/* CreateComponent */ +, (vm, { + op1: flags, + op2: _state +}) => { + let instance = vm.fetchValue(_state); + let { + definition, + manager, + capabilities + } = instance; + + if (!managerHasCapability(manager, capabilities, 512 + /* CreateInstance */ + )) { + // TODO: Closure and Main components are always invoked dynamically, so this + // opcode may run even if this capability is not enabled. In the future we + // should handle this in a better way. + return; + } + + let dynamicScope = null; + + if (managerHasCapability(manager, capabilities, 64 + /* DynamicScope */ + )) { + dynamicScope = vm.dynamicScope(); + } + + let hasDefaultBlock = flags & 1; + let args = null; + + if (managerHasCapability(manager, capabilities, 8 + /* CreateArgs */ + )) { + args = vm.stack.peek(); + } + + let self = null; + + if (managerHasCapability(manager, capabilities, 128 + /* CreateCaller */ + )) { + self = vm.getSelf(); + } + + let state = manager.create(vm.getOwner(), definition.state, args, vm.env, dynamicScope, self, !!hasDefaultBlock); // We want to reuse the `state` POJO here, because we know that the opcodes + // only transition at exactly one place. + + instance.state = state; + + if (managerHasCapability(manager, capabilities, 256 + /* UpdateHook */ + )) { + vm.updateWith(new UpdateComponentOpcode(state, manager, dynamicScope)); + } +}); +APPEND_OPCODES.add(88 +/* RegisterComponentDestructor */ +, (vm, { + op1: _state +}) => { + let { + manager, + state, + capabilities + } = vm.fetchValue(_state); + let d = manager.getDestroyable(state); + + if (DEBUG && !managerHasCapability(manager, capabilities, 2048 + /* WillDestroy */ + ) && d !== null && typeof 'willDestroy' in d) { + throw new Error('BUG: Destructor has willDestroy, but the willDestroy capability was not enabled for this component. Pre-destruction hooks must be explicitly opted into'); + } + + if (d) vm.associateDestroyable(d); +}); +APPEND_OPCODES.add(97 +/* BeginComponentTransaction */ +, (vm, { + op1: _state +}) => { + var _a; + + let name; + + if (DEBUG) { + let { + definition, + manager + } = vm.fetchValue(_state); + name = (_a = definition.resolvedName) !== null && _a !== void 0 ? _a : manager.getDebugName(definition.state); + } + + vm.beginCacheGroup(name); + vm.elements().pushSimpleBlock(); +}); +APPEND_OPCODES.add(89 +/* PutComponentOperations */ +, vm => { + vm.loadValue($t0, new ComponentElementOperations()); +}); +APPEND_OPCODES.add(53 +/* ComponentAttr */ +, (vm, { + op1: _name, + op2: _trusting, + op3: _namespace +}) => { + let name = vm[CONSTANTS].getValue(_name); + let trusting = vm[CONSTANTS].getValue(_trusting); + let reference = vm.stack.pop(); + let namespace = _namespace ? vm[CONSTANTS].getValue(_namespace) : null; + vm.fetchValue($t0).setAttribute(name, reference, trusting, namespace); +}); +APPEND_OPCODES.add(105 +/* StaticComponentAttr */ +, (vm, { + op1: _name, + op2: _value, + op3: _namespace +}) => { + let name = vm[CONSTANTS].getValue(_name); + let value = vm[CONSTANTS].getValue(_value); + let namespace = _namespace ? vm[CONSTANTS].getValue(_namespace) : null; + vm.fetchValue($t0).setStaticAttribute(name, value, namespace); +}); +class ComponentElementOperations { + constructor() { + this.attributes = dict(); + this.classes = []; + this.modifiers = []; + } + + setAttribute(name, value, trusting, namespace) { + let deferred = { + value, + namespace, + trusting + }; + + if (name === 'class') { + this.classes.push(value); + } + + this.attributes[name] = deferred; + } + + setStaticAttribute(name, value, namespace) { + let deferred = { + value, + namespace + }; + + if (name === 'class') { + this.classes.push(value); + } + + this.attributes[name] = deferred; + } + + addModifier(modifier) { + this.modifiers.push(modifier); + } + + flush(vm) { + let type; + let attributes = this.attributes; + + for (let name in this.attributes) { + if (name === 'type') { + type = attributes[name]; + continue; + } + + let attr = this.attributes[name]; + + if (name === 'class') { + setDeferredAttr(vm, 'class', mergeClasses(this.classes), attr.namespace, attr.trusting); + } else { + setDeferredAttr(vm, name, attr.value, attr.namespace, attr.trusting); + } + } + + if (type !== undefined) { + setDeferredAttr(vm, 'type', type.value, type.namespace, type.trusting); + } + + return this.modifiers; + } + +} + +function mergeClasses(classes) { + if (classes.length === 0) { + return ''; + } + + if (classes.length === 1) { + return classes[0]; + } + + if (allStringClasses(classes)) { + return classes.join(' '); + } + + return createClassListRef(classes); +} + +function allStringClasses(classes) { + for (let i = 0; i < classes.length; i++) { + if (typeof classes[i] !== 'string') { + return false; + } + } + + return true; +} + +function setDeferredAttr(vm, name, value, namespace, trusting = false) { + if (typeof value === 'string') { + vm.elements().setStaticAttribute(name, value, namespace); + } else { + let attribute = vm.elements().setDynamicAttribute(name, valueForRef(value), trusting, namespace); + + if (!isConstRef(value)) { + vm.updateWith(new UpdateDynamicAttributeOpcode(value, attribute, vm.env)); + } + } +} + +APPEND_OPCODES.add(99 +/* DidCreateElement */ +, (vm, { + op1: _state +}) => { + let { + definition, + state + } = vm.fetchValue(_state); + let { + manager + } = definition; + let operations = vm.fetchValue($t0); + manager.didCreateElement(state, vm.elements().constructing, operations); +}); +APPEND_OPCODES.add(90 +/* GetComponentSelf */ +, (vm, { + op1: _state, + op2: _names +}) => { + var _a; + + let instance = vm.fetchValue(_state); + let { + definition, + state + } = instance; + let { + manager + } = definition; + let selfRef = manager.getSelf(state); + + if (vm.env.debugRenderTree !== undefined) { + let instance = vm.fetchValue(_state); + let { + definition, + manager + } = instance; + let args; + + if (vm.stack.peek() === vm[ARGS]) { + args = vm[ARGS].capture(); + } else { + let names = vm[CONSTANTS].getArray(_names); + vm[ARGS].setup(vm.stack, names, [], 0, true); + args = vm[ARGS].capture(); + } + + let moduleName; + let compilable = definition.compilable; + + if (compilable === null) { + compilable = manager.getDynamicLayout(state, vm.runtime.resolver); + + if (compilable !== null) { + moduleName = compilable.moduleName; + } else { + moduleName = '__default__.hbs'; + } + } else { + moduleName = compilable.moduleName; + } // For tearing down the debugRenderTree + + + vm.associateDestroyable(instance); + + if (hasCustomDebugRenderTreeLifecycle(manager)) { + let nodes = manager.getDebugCustomRenderTree(instance.definition.state, instance.state, args, moduleName); + nodes.forEach(node => { + let { + bucket + } = node; + vm.env.debugRenderTree.create(bucket, node); + registerDestructor(instance, () => { + var _a; + + (_a = vm.env.debugRenderTree) === null || _a === void 0 ? void 0 : _a.willDestroy(bucket); + }); + vm.updateWith(new DebugRenderTreeUpdateOpcode(bucket)); + }); + } else { + let name = (_a = definition.resolvedName) !== null && _a !== void 0 ? _a : manager.getDebugName(definition.state); + vm.env.debugRenderTree.create(instance, { + type: 'component', + name, + args, + template: moduleName, + instance: valueForRef(selfRef) + }); + vm.associateDestroyable(instance); + registerDestructor(instance, () => { + var _a; + + (_a = vm.env.debugRenderTree) === null || _a === void 0 ? void 0 : _a.willDestroy(instance); + }); + vm.updateWith(new DebugRenderTreeUpdateOpcode(instance)); + } + } + + vm.stack.push(selfRef); +}); +APPEND_OPCODES.add(91 +/* GetComponentTagName */ +, (vm, { + op1: _state +}) => { + let { + definition, + state + } = vm.fetchValue(_state); + let { + manager + } = definition; + let tagName = manager.getTagName(state); // User provided value from JS, so we don't bother to encode + + vm.stack.push(tagName); +}); // Dynamic Invocation Only + +APPEND_OPCODES.add(92 +/* GetComponentLayout */ +, (vm, { + op1: _state +}) => { + let instance = vm.fetchValue(_state); + let { + manager, + definition + } = instance; + let { + stack + } = vm; + let { + compilable + } = definition; + + if (compilable === null) { + let { + capabilities + } = instance; + compilable = manager.getDynamicLayout(instance.state, vm.runtime.resolver); + + if (compilable === null) { + if (managerHasCapability(manager, capabilities, 1024 + /* Wrapped */ + )) { + compilable = unwrapTemplate(vm[CONSTANTS].defaultTemplate).asWrappedLayout(); + } else { + compilable = unwrapTemplate(vm[CONSTANTS].defaultTemplate).asLayout(); + } + } + } + + let handle = compilable.compile(vm.context); + stack.push(compilable.symbolTable); + stack.push(handle); +}); +APPEND_OPCODES.add(75 +/* Main */ +, (vm, { + op1: register +}) => { + let definition = vm.stack.pop(); + let invocation = vm.stack.pop(); + let { + manager, + capabilities + } = definition; + let state = { + definition, + manager, + capabilities, + state: null, + handle: invocation.handle, + table: invocation.symbolTable, + lookup: null + }; + vm.loadValue(register, state); +}); +APPEND_OPCODES.add(95 +/* PopulateLayout */ +, (vm, { + op1: _state +}) => { + let { + stack + } = vm; // In DEBUG handles could be ErrHandle objects + + let handle = stack.pop(); + let table = stack.pop(); + let state = vm.fetchValue(_state); + state.handle = handle; + state.table = table; +}); +APPEND_OPCODES.add(38 +/* VirtualRootScope */ +, (vm, { + op1: _state +}) => { + let { + table, + manager, + capabilities, + state + } = vm.fetchValue(_state); + let owner; + + if (managerHasCapability(manager, capabilities, 4096 + /* HasSubOwner */ + )) { + owner = manager.getOwner(state); + vm.loadValue($t1, null); // Clear the temp register + } else { + // Check the temp register to see if an owner was resolved from currying + owner = vm.fetchValue($t1); + + if (owner === null) { + // If an owner wasn't found, default to using the current owner. This + // will happen for normal dynamic component invocation, + // e.g. + owner = vm.getOwner(); + } else { + // Else the owner was found, so clear the temp register. This will happen + // if we are loading a curried component, e.g. <@someCurriedComponent/> + vm.loadValue($t1, null); + } + } + + vm.pushRootScope(table.symbols.length + 1, owner); +}); +APPEND_OPCODES.add(94 +/* SetupForEval */ +, (vm, { + op1: _state +}) => { + let state = vm.fetchValue(_state); + + if (state.table.hasEval) { + let lookup = state.lookup = dict(); + vm.scope().bindEvalScope(lookup); + } +}); +APPEND_OPCODES.add(17 +/* SetNamedVariables */ +, (vm, { + op1: _state +}) => { + let state = vm.fetchValue(_state); + let scope = vm.scope(); + let args = vm.stack.peek(); + let callerNames = args.named.atNames; + + for (let i = callerNames.length - 1; i >= 0; i--) { + let atName = callerNames[i]; + let symbol$$1 = state.table.symbols.indexOf(callerNames[i]); + let value = args.named.get(atName, true); + if (symbol$$1 !== -1) scope.bindSymbol(symbol$$1 + 1, value); + if (state.lookup) state.lookup[atName] = value; + } +}); + +function bindBlock(symbolName, blockName, state, blocks, vm) { + let symbol$$1 = state.table.symbols.indexOf(symbolName); + let block = blocks.get(blockName); + if (symbol$$1 !== -1) vm.scope().bindBlock(symbol$$1 + 1, block); + if (state.lookup) state.lookup[symbolName] = block; +} + +APPEND_OPCODES.add(18 +/* SetBlocks */ +, (vm, { + op1: _state +}) => { + let state = vm.fetchValue(_state); + let { + blocks + } = vm.stack.peek(); + + for (let i = 0; i < blocks.names.length; i++) { + bindBlock(blocks.symbolNames[i], blocks.names[i], state, blocks, vm); + } +}); // Dynamic Invocation Only + +APPEND_OPCODES.add(96 +/* InvokeComponentLayout */ +, (vm, { + op1: _state +}) => { + let state = vm.fetchValue(_state); + vm.call(state.handle); +}); +APPEND_OPCODES.add(100 +/* DidRenderLayout */ +, (vm, { + op1: _state +}) => { + let instance = vm.fetchValue(_state); + let { + manager, + state, + capabilities + } = instance; + let bounds = vm.elements().popBlock(); + + if (vm.env.debugRenderTree !== undefined) { + if (hasCustomDebugRenderTreeLifecycle(manager)) { + let nodes = manager.getDebugCustomRenderTree(instance.definition.state, state, EMPTY_ARGS); + nodes.reverse().forEach(node => { + let { + bucket + } = node; + vm.env.debugRenderTree.didRender(bucket, bounds); + vm.updateWith(new DebugRenderTreeDidRenderOpcode(bucket, bounds)); + }); + } else { + vm.env.debugRenderTree.didRender(instance, bounds); + vm.updateWith(new DebugRenderTreeDidRenderOpcode(instance, bounds)); + } + } + + if (managerHasCapability(manager, capabilities, 512 + /* CreateInstance */ + )) { + let mgr = manager; + mgr.didRenderLayout(state, bounds); + vm.env.didCreate(instance); + vm.updateWith(new DidUpdateLayoutOpcode(instance, bounds)); + } +}); +APPEND_OPCODES.add(98 +/* CommitComponentTransaction */ +, vm => { + vm.commitCacheGroup(); +}); +class UpdateComponentOpcode { + constructor(component, manager, dynamicScope) { + this.component = component; + this.manager = manager; + this.dynamicScope = dynamicScope; + } + + evaluate(_vm) { + let { + component, + manager, + dynamicScope + } = this; + manager.update(component, dynamicScope); + } + +} +class DidUpdateLayoutOpcode { + constructor(component, bounds) { + this.component = component; + this.bounds = bounds; + } + + evaluate(vm) { + let { + component, + bounds + } = this; + let { + manager, + state + } = component; + manager.didUpdateLayout(state, bounds); + vm.env.didUpdate(component); + } + +} + +class DebugRenderTreeUpdateOpcode { + constructor(bucket) { + this.bucket = bucket; + } + + evaluate(vm) { + var _a; + + (_a = vm.env.debugRenderTree) === null || _a === void 0 ? void 0 : _a.update(this.bucket); + } + +} + +class DebugRenderTreeDidRenderOpcode { + constructor(bucket, bounds) { + this.bucket = bucket; + this.bounds = bounds; + } + + evaluate(vm) { + var _a; + + (_a = vm.env.debugRenderTree) === null || _a === void 0 ? void 0 : _a.didRender(this.bucket, this.bounds); + } + +} + +class DynamicTextContent { + constructor(node, reference, lastValue) { + this.node = node; + this.reference = reference; + this.lastValue = lastValue; + } + + evaluate() { + let value = valueForRef(this.reference); + let { + lastValue + } = this; + if (value === lastValue) return; + let normalized; + + if (isEmpty(value)) { + normalized = ''; + } else if (isString(value)) { + normalized = value; + } else { + normalized = String(value); + } + + if (normalized !== lastValue) { + let textNode = this.node; + textNode.nodeValue = this.lastValue = normalized; + } + } + +} + +function toContentType(value) { + if (shouldCoerce(value)) { + return 2 + /* String */ + ; + } else if (isCurriedType(value, 0 + /* Component */ + ) || hasInternalComponentManager(value)) { + return 0 + /* Component */ + ; + } else if (isCurriedType(value, 1 + /* Helper */ + ) || hasInternalHelperManager(value)) { + return 1 + /* Helper */ + ; + } else if (isSafeString(value)) { + return 4 + /* SafeString */ + ; + } else if (isFragment(value)) { + return 5 + /* Fragment */ + ; + } else if (isNode(value)) { + return 6 + /* Node */ + ; + } else { + return 2 + /* String */ + ; + } +} + +function toDynamicContentType(value) { + if (!isObject(value)) { + return 2 + /* String */ + ; + } + + if (isCurriedType(value, 0 + /* Component */ + ) || hasInternalComponentManager(value)) { + return 0 + /* Component */ + ; + } else { + if (DEBUG && !isCurriedType(value, 1 + /* Helper */ + ) && !hasInternalHelperManager(value)) { + throw new Error(`Attempted use a dynamic value as a component or helper, but that value did not have an associated component or helper manager. The value was: ${value}`); + } + + return 1 + /* Helper */ + ; + } +} + +APPEND_OPCODES.add(76 +/* ContentType */ +, vm => { + let reference = vm.stack.peek(); + vm.stack.push(toContentType(valueForRef(reference))); + + if (!isConstRef(reference)) { + vm.updateWith(new AssertFilter(reference, toContentType)); + } +}); +APPEND_OPCODES.add(106 +/* DynamicContentType */ +, vm => { + let reference = vm.stack.peek(); + vm.stack.push(toDynamicContentType(valueForRef(reference))); + + if (!isConstRef(reference)) { + vm.updateWith(new AssertFilter(reference, toDynamicContentType)); + } +}); +APPEND_OPCODES.add(43 +/* AppendHTML */ +, vm => { + let reference = vm.stack.pop(); + let rawValue = valueForRef(reference); + let value = isEmpty(rawValue) ? '' : String(rawValue); + vm.elements().appendDynamicHTML(value); +}); +APPEND_OPCODES.add(44 +/* AppendSafeHTML */ +, vm => { + let reference = vm.stack.pop(); + let rawValue = valueForRef(reference).toHTML(); + let value = isEmpty(rawValue) ? '' : rawValue; + vm.elements().appendDynamicHTML(value); +}); +APPEND_OPCODES.add(47 +/* AppendText */ +, vm => { + let reference = vm.stack.pop(); + let rawValue = valueForRef(reference); + let value = isEmpty(rawValue) ? '' : String(rawValue); + let node = vm.elements().appendDynamicText(value); + + if (!isConstRef(reference)) { + vm.updateWith(new DynamicTextContent(node, reference, value)); + } +}); +APPEND_OPCODES.add(45 +/* AppendDocumentFragment */ +, vm => { + let reference = vm.stack.pop(); + let value = valueForRef(reference); + vm.elements().appendDynamicFragment(value); +}); +APPEND_OPCODES.add(46 +/* AppendNode */ +, vm => { + let reference = vm.stack.pop(); + let value = valueForRef(reference); + vm.elements().appendDynamicNode(value); +}); + +function debugCallback(context, get) { + // eslint-disable-next-line no-console + console.info('Use `context`, and `get()` to debug this template.'); // for example... + // eslint-disable-next-line no-unused-expressions + + context === get('this'); // eslint-disable-next-line no-debugger + + debugger; +} + +let callback = debugCallback; // For testing purposes + +function setDebuggerCallback(cb) { + callback = cb; +} +function resetDebuggerCallback() { + callback = debugCallback; +} + +class ScopeInspector { + constructor(scope, symbols, evalInfo) { + this.scope = scope; + this.locals = dict(); + + for (let i = 0; i < evalInfo.length; i++) { + let slot = evalInfo[i]; + let name = symbols[slot - 1]; + let ref = scope.getSymbol(slot); + this.locals[name] = ref; + } + } + + get(path) { + let { + scope, + locals + } = this; + let parts = path.split('.'); + let [head, ...tail] = path.split('.'); + let evalScope = scope.getEvalScope(); + let ref; + + if (head === 'this') { + ref = scope.getSelf(); + } else if (locals[head]) { + ref = locals[head]; + } else if (head.indexOf('@') === 0 && evalScope[head]) { + ref = evalScope[head]; + } else { + ref = this.scope.getSelf(); + tail = parts; + } + + return tail.reduce((r, part) => childRefFor(r, part), ref); + } + +} + +APPEND_OPCODES.add(103 +/* Debugger */ +, (vm, { + op1: _symbols, + op2: _evalInfo +}) => { + let symbols = vm[CONSTANTS].getArray(_symbols); + let evalInfo = vm[CONSTANTS].getArray(decodeHandle(_evalInfo)); + let inspector = new ScopeInspector(vm.scope(), symbols, evalInfo); + callback(valueForRef(vm.getSelf()), path => valueForRef(inspector.get(path))); +}); + +APPEND_OPCODES.add(101 +/* InvokePartial */ +, (vm, { + op1: _symbols, + op2: _evalInfo +}) => { + let { + [CONSTANTS]: constants, + stack + } = vm; + let name = valueForRef(stack.pop()); + let outerScope = vm.scope(); + let owner = outerScope.owner; + let outerSymbols = constants.getArray(_symbols); + let evalInfo = constants.getArray(decodeHandle(_evalInfo)); + let definition = vm.runtime.resolver.lookupPartial(name, owner); + let { + symbolTable, + handle: vmHandle + } = definition.getPartial(vm.context); + { + let partialSymbols = symbolTable.symbols; + let partialScope = vm.pushRootScope(partialSymbols.length, owner); + let evalScope = outerScope.getEvalScope(); + partialScope.bindEvalScope(evalScope); + partialScope.bindSelf(outerScope.getSelf()); + let locals = Object.create(outerScope.getPartialMap()); + + for (let i = 0; i < evalInfo.length; i++) { + let slot = evalInfo[i]; + + if (slot !== -1) { + let name = outerSymbols[slot - 1]; + let ref = outerScope.getSymbol(slot); + locals[name] = ref; + } + } + + if (evalScope) { + for (let i = 0; i < partialSymbols.length; i++) { + let name = partialSymbols[i]; + let symbol$$1 = i + 1; + let value = evalScope[name]; + if (value !== undefined) partialScope.bind(symbol$$1, value); + } + } + + partialScope.bindPartialMap(locals); + vm.pushFrame(); // sp += 2 + + vm.call(unwrapHandle(vmHandle)); + } +}); + +APPEND_OPCODES.add(72 +/* EnterList */ +, (vm, { + op1: relativeStart, + op2: elseTarget +}) => { + let stack = vm.stack; + let listRef = stack.pop(); + let keyRef = stack.pop(); + let keyValue = valueForRef(keyRef); + let key = keyValue === null ? '@identity' : String(keyValue); + let iteratorRef = createIteratorRef(listRef, key); + let iterator = valueForRef(iteratorRef); + vm.updateWith(new AssertFilter(iteratorRef, iterator => iterator.isEmpty())); + + if (iterator.isEmpty() === true) { + // TODO: Fix this offset, should be accurate + vm.goto(elseTarget + 1); + } else { + vm.enterList(iteratorRef, relativeStart); + vm.stack.push(iterator); + } +}); +APPEND_OPCODES.add(73 +/* ExitList */ +, vm => { + vm.exitList(); +}); +APPEND_OPCODES.add(74 +/* Iterate */ +, (vm, { + op1: breaks +}) => { + let stack = vm.stack; + let iterator = stack.peek(); + let item = iterator.next(); + + if (item !== null) { + vm.registerItem(vm.enterItem(item)); + } else { + vm.goto(breaks); + } +}); + +const CAPABILITIES = { + dynamicLayout: false, + dynamicTag: false, + prepareArgs: false, + createArgs: false, + attributeHook: false, + elementHook: false, + createCaller: false, + dynamicScope: false, + updateHook: false, + createInstance: false, + wrapped: false, + willDestroy: false, + hasSubOwner: false +}; +class TemplateOnlyComponentManager { + getCapabilities() { + return CAPABILITIES; + } + + getDebugName({ + name + }) { + return name; + } + + getSelf() { + return NULL_REFERENCE; + } + + getDestroyable() { + return null; + } + +} +const TEMPLATE_ONLY_COMPONENT_MANAGER = new TemplateOnlyComponentManager(); // This is only exported for types, don't use this class directly + +class TemplateOnlyComponentDefinition { + constructor(moduleName = '@glimmer/component/template-only', name = '(unknown template-only component)') { + this.moduleName = moduleName; + this.name = name; + } + + toString() { + return this.moduleName; + } + +} +setInternalComponentManager(TEMPLATE_ONLY_COMPONENT_MANAGER, TemplateOnlyComponentDefinition.prototype); +/** + This utility function is used to declare a given component has no backing class. When the rendering engine detects this it + is able to perform a number of optimizations. Templates that are associated with `templateOnly()` will be rendered _as is_ + without adding a wrapping `
` (or any of the other element customization behaviors of [@ember/component](/ember/release/classes/Component)). + Specifically, this means that the template will be rendered as "outer HTML". + + In general, this method will be used by build time tooling and would not be directly written in an application. However, + at times it may be useful to use directly to leverage the "outer HTML" semantics mentioned above. For example, if an addon would like + to use these semantics for its templates but cannot be certain it will only be consumed by applications that have enabled the + `template-only-glimmer-components` optional feature. + + @example + + ```js + import { templateOnlyComponent } from '@glimmer/runtime'; + + export default templateOnlyComponent(); + ``` + + @public + @method templateOnly + @param {String} moduleName the module name that the template only component represents, this will be used for debugging purposes + @category EMBER_GLIMMER_SET_COMPONENT_TEMPLATE +*/ + +function templateOnlyComponent(moduleName, name) { + return new TemplateOnlyComponentDefinition(moduleName, name); +} + +// http://www.w3.org/TR/html/syntax.html#html-integration-point +const SVG_INTEGRATION_POINTS = { + foreignObject: 1, + desc: 1, + title: 1 +}; // http://www.w3.org/TR/html/syntax.html#adjust-svg-attributes +// TODO: Adjust SVG attributes +// http://www.w3.org/TR/html/syntax.html#parsing-main-inforeign +// TODO: Adjust SVG elements +// http://www.w3.org/TR/html/syntax.html#parsing-main-inforeign + +const BLACKLIST_TABLE = Object.create(null); +class DOMOperations { + constructor(document) { + this.document = document; + this.setupUselessElement(); + } // split into separate method so that NodeDOMTreeConstruction + // can override it. + + + setupUselessElement() { + this.uselessElement = this.document.createElement('div'); + } + + createElement(tag, context) { + let isElementInSVGNamespace, isHTMLIntegrationPoint; + + if (context) { + isElementInSVGNamespace = context.namespaceURI === "http://www.w3.org/2000/svg" + /* SVG */ + || tag === 'svg'; + isHTMLIntegrationPoint = !!SVG_INTEGRATION_POINTS[context.tagName]; + } else { + isElementInSVGNamespace = tag === 'svg'; + isHTMLIntegrationPoint = false; + } + + if (isElementInSVGNamespace && !isHTMLIntegrationPoint) { + // FIXME: This does not properly handle with color, face, or + // size attributes, which is also disallowed by the spec. We should fix + // this. + if (BLACKLIST_TABLE[tag]) { + throw new Error(`Cannot create a ${tag} inside an SVG context`); + } + + return this.document.createElementNS("http://www.w3.org/2000/svg" + /* SVG */ + , tag); + } else { + return this.document.createElement(tag); + } + } + + insertBefore(parent, node, reference) { + parent.insertBefore(node, reference); + } + + insertHTMLBefore(parent, nextSibling, html) { + if (html === '') { + let comment = this.createComment(''); + parent.insertBefore(comment, nextSibling); + return new ConcreteBounds(parent, comment, comment); + } + + let prev = nextSibling ? nextSibling.previousSibling : parent.lastChild; + let last; + + if (nextSibling === null) { + parent.insertAdjacentHTML("beforeend" + /* beforeend */ + , html); + last = parent.lastChild; + } else if (nextSibling instanceof HTMLElement) { + nextSibling.insertAdjacentHTML('beforebegin', html); + last = nextSibling.previousSibling; + } else { + // Non-element nodes do not support insertAdjacentHTML, so add an + // element and call it on that element. Then remove the element. + // + // This also protects Edge, IE and Firefox w/o the inspector open + // from merging adjacent text nodes. See ./compat/text-node-merging-fix.ts + let { + uselessElement + } = this; + parent.insertBefore(uselessElement, nextSibling); + uselessElement.insertAdjacentHTML("beforebegin" + /* beforebegin */ + , html); + last = uselessElement.previousSibling; + parent.removeChild(uselessElement); + } + + let first = prev ? prev.nextSibling : parent.firstChild; + return new ConcreteBounds(parent, first, last); + } + + createTextNode(text) { + return this.document.createTextNode(text); + } + + createComment(data) { + return this.document.createComment(data); + } + +} +function moveNodesBefore(source, target, nextSibling) { + let first = source.firstChild; + let last = first; + let current = first; + + while (current) { + let next = current.nextSibling; + target.insertBefore(current, nextSibling); + last = current; + current = next; + } + + return new ConcreteBounds(target, first, last); +} + +const SVG_NAMESPACE = "http://www.w3.org/2000/svg" +/* SVG */ +; // Patch: insertAdjacentHTML on SVG Fix +// Browsers: Safari, IE, Edge, Firefox ~33-34 +// Reason: insertAdjacentHTML does not exist on SVG elements in Safari. It is +// present but throws an exception on IE and Edge. Old versions of +// Firefox create nodes in the incorrect namespace. +// Fix: Since IE and Edge silently fail to create SVG nodes using +// innerHTML, and because Firefox may create nodes in the incorrect +// namespace using innerHTML on SVG elements, an HTML-string wrapping +// approach is used. A pre/post SVG tag is added to the string, then +// that whole string is added to a div. The created nodes are plucked +// out and applied to the target location on DOM. + +function applySVGInnerHTMLFix(document, DOMClass, svgNamespace) { + if (!document) return DOMClass; + + if (!shouldApplyFix(document, svgNamespace)) { + return DOMClass; + } + + let div = document.createElement('div'); + return class DOMChangesWithSVGInnerHTMLFix extends DOMClass { + insertHTMLBefore(parent, nextSibling, html) { + if (html === '') { + return super.insertHTMLBefore(parent, nextSibling, html); + } + + if (parent.namespaceURI !== svgNamespace) { + return super.insertHTMLBefore(parent, nextSibling, html); + } + + return fixSVG(parent, div, html, nextSibling); + } + + }; +} + +function fixSVG(parent, div, html, reference) { + let source; // This is important, because descendants of the integration + // point are parsed in the HTML namespace + + if (parent.tagName.toUpperCase() === 'FOREIGNOBJECT') { + // IE, Edge: also do not correctly support using `innerHTML` on SVG + // namespaced elements. So here a wrapper is used. + let wrappedHtml = '' + html + ''; + clearElement(div); + div.insertAdjacentHTML("afterbegin" + /* afterbegin */ + , wrappedHtml); + source = div.firstChild.firstChild; + } else { + // IE, Edge: also do not correctly support using `innerHTML` on SVG + // namespaced elements. So here a wrapper is used. + let wrappedHtml = '' + html + ''; + clearElement(div); + div.insertAdjacentHTML("afterbegin" + /* afterbegin */ + , wrappedHtml); + source = div.firstChild; + } + + return moveNodesBefore(source, parent, reference); +} + +function shouldApplyFix(document, svgNamespace) { + let svg = document.createElementNS(svgNamespace, 'svg'); + + try { + svg.insertAdjacentHTML("beforeend" + /* beforeend */ + , ''); + } catch (e) {// IE, Edge: Will throw, insertAdjacentHTML is unsupported on SVG + // Safari: Will throw, insertAdjacentHTML is not present on SVG + } finally { + // FF: Old versions will create a node in the wrong namespace + if (svg.childNodes.length === 1 && svg.firstChild.namespaceURI === SVG_NAMESPACE) { + // The test worked as expected, no fix required + return false; + } + + return true; + } +} + +// Patch: Adjacent text node merging fix +// Browsers: IE, Edge, Firefox w/o inspector open +// Reason: These browsers will merge adjacent text nodes. For example given +//
Hello
with div.insertAdjacentHTML(' world') browsers +// with proper behavior will populate div.childNodes with two items. +// These browsers will populate it with one merged node instead. +// Fix: Add these nodes to a wrapper element, then iterate the childNodes +// of that wrapper and move the nodes to their target location. Note +// that potential SVG bugs will have been handled before this fix. +// Note that this fix must only apply to the previous text node, as +// the base implementation of `insertHTMLBefore` already handles +// following text nodes correctly. +function applyTextNodeMergingFix(document, DOMClass) { + if (!document) return DOMClass; + + if (!shouldApplyFix$1(document)) { + return DOMClass; + } + + return class DOMChangesWithTextNodeMergingFix extends DOMClass { + constructor(document) { + super(document); + this.uselessComment = document.createComment(''); + } + + insertHTMLBefore(parent, nextSibling, html) { + if (html === '') { + return super.insertHTMLBefore(parent, nextSibling, html); + } + + let didSetUselessComment = false; + let nextPrevious = nextSibling ? nextSibling.previousSibling : parent.lastChild; + + if (nextPrevious && nextPrevious instanceof Text) { + didSetUselessComment = true; + parent.insertBefore(this.uselessComment, nextSibling); + } + + let bounds = super.insertHTMLBefore(parent, nextSibling, html); + + if (didSetUselessComment) { + parent.removeChild(this.uselessComment); + } + + return bounds; + } + + }; +} + +function shouldApplyFix$1(document) { + let mergingTextDiv = document.createElement('div'); + mergingTextDiv.appendChild(document.createTextNode('first')); + mergingTextDiv.insertAdjacentHTML("beforeend" + /* beforeend */ + , 'second'); + + if (mergingTextDiv.childNodes.length === 2) { + // It worked as expected, no fix required + return false; + } + + return true; +} + +['b', 'big', 'blockquote', 'body', 'br', 'center', 'code', 'dd', 'div', 'dl', 'dt', 'em', 'embed', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'i', 'img', 'li', 'listing', 'main', 'meta', 'nobr', 'ol', 'p', 'pre', 'ruby', 's', 'small', 'span', 'strong', 'strike', 'sub', 'sup', 'table', 'tt', 'u', 'ul', 'var'].forEach(tag => BLACKLIST_TABLE[tag] = 1); +const WHITESPACE = /[\t-\r \xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/; +let doc = typeof document === 'undefined' ? null : document; +function isWhitespace(string) { + return WHITESPACE.test(string); +} +var DOM; + +(function (DOM) { + class TreeConstruction extends DOMOperations { + createElementNS(namespace, tag) { + return this.document.createElementNS(namespace, tag); + } + + setAttribute(element, name, value, namespace = null) { + if (namespace) { + element.setAttributeNS(namespace, name, value); + } else { + element.setAttribute(name, value); + } + } + + } + + DOM.TreeConstruction = TreeConstruction; + let appliedTreeConstruction = TreeConstruction; + appliedTreeConstruction = applyTextNodeMergingFix(doc, appliedTreeConstruction); + appliedTreeConstruction = applySVGInnerHTMLFix(doc, appliedTreeConstruction, "http://www.w3.org/2000/svg" + /* SVG */ + ); + DOM.DOMTreeConstruction = appliedTreeConstruction; +})(DOM || (DOM = {})); + +class DOMChangesImpl extends DOMOperations { + constructor(document) { + super(document); + this.document = document; + this.namespace = null; + } + + setAttribute(element, name, value) { + element.setAttribute(name, value); + } + + removeAttribute(element, name) { + element.removeAttribute(name); + } + + insertAfter(element, node, reference) { + this.insertBefore(element, node, reference.nextSibling); + } + +} +let helper = DOMChangesImpl; +helper = applyTextNodeMergingFix(doc, helper); +helper = applySVGInnerHTMLFix(doc, helper, "http://www.w3.org/2000/svg" +/* SVG */ +); +var helper$1 = helper; +const DOMTreeConstruction = DOM.DOMTreeConstruction; + +let GUID = 0; +class Ref { + constructor(value) { + this.id = GUID++; + this.value = value; + } + + get() { + return this.value; + } + + release() { + if (DEBUG && this.value === null) { + throw new Error('BUG: double release?'); + } + + this.value = null; + } + + toString() { + let label = `Ref ${this.id}`; + + if (this.value === null) { + return `${label} (released)`; + } else { + try { + return `${label}: ${this.value}`; + } catch (_a) { + return label; + } + } + } + +} +class DebugRenderTreeImpl { + constructor() { + this.stack = new Stack(); + this.refs = new WeakMap(); + this.roots = new Set(); + this.nodes = new WeakMap(); + } + + begin() { + this.reset(); + } + + create(state, node) { + let internalNode = assign({}, node, { + bounds: null, + refs: new Set() + }); + this.nodes.set(state, internalNode); + this.appendChild(internalNode, state); + this.enter(state); + } + + update(state) { + this.enter(state); + } + + didRender(state, bounds) { + if (DEBUG && this.stack.current !== state) { + throw new Error(`BUG: expecting ${this.stack.current}, got ${state}`); + } + + this.nodeFor(state).bounds = bounds; + this.exit(); + } + + willDestroy(state) { + this.refs.get(state).release(); + } + + commit() { + this.reset(); + } + + capture() { + return this.captureRefs(this.roots); + } + + reset() { + if (this.stack.size !== 0) { + // We probably encountered an error during the rendering loop. This will + // likely trigger undefined behavior and memory leaks as the error left + // things in an inconsistent state. It is recommended that the user + // refresh the page. + // TODO: We could warn here? But this happens all the time in our tests? + // Clean up the root reference to prevent errors from happening if we + // attempt to capture the render tree (Ember Inspector may do this) + let root = this.stack.toArray()[0]; + let ref = this.refs.get(root); + + if (ref !== undefined) { + this.roots.delete(ref); + } + + while (!this.stack.isEmpty()) { + this.stack.pop(); + } + } + } + + enter(state) { + this.stack.push(state); + } + + exit() { + if (DEBUG && this.stack.size === 0) { + throw new Error('BUG: unbalanced pop'); + } + + this.stack.pop(); + } + + nodeFor(state) { + return this.nodes.get(state); + } + + appendChild(node, state) { + if (DEBUG && this.refs.has(state)) { + throw new Error('BUG: child already appended'); + } + + let parent = this.stack.current; + let ref = new Ref(state); + this.refs.set(state, ref); + + if (parent) { + let parentNode = this.nodeFor(parent); + parentNode.refs.add(ref); + node.parent = parentNode; + } else { + this.roots.add(ref); + } + } + + captureRefs(refs) { + let captured = []; + refs.forEach(ref => { + let state = ref.get(); + + if (state) { + captured.push(this.captureNode(`render-node:${ref.id}`, state)); + } else { + refs.delete(ref); + } + }); + return captured; + } + + captureNode(id, state) { + let node = this.nodeFor(state); + let { + type, + name, + args, + instance, + refs + } = node; + let template = this.captureTemplate(node); + let bounds = this.captureBounds(node); + let children = this.captureRefs(refs); + return { + id, + type, + name, + args: reifyArgs(args), + instance, + template, + bounds, + children + }; + } + + captureTemplate({ + template + }) { + return template || null; + } + + captureBounds(node) { + let bounds = node.bounds; + let parentElement = bounds.parentElement(); + let firstNode = bounds.firstNode(); + let lastNode = bounds.lastNode(); + return { + parentElement, + firstNode, + lastNode + }; + } + +} + +var _a$1; +const TRANSACTION = symbol('TRANSACTION'); + +class TransactionImpl { + constructor() { + this.scheduledInstallModifiers = []; + this.scheduledUpdateModifiers = []; + this.createdComponents = []; + this.updatedComponents = []; + } + + didCreate(component) { + this.createdComponents.push(component); + } + + didUpdate(component) { + this.updatedComponents.push(component); + } + + scheduleInstallModifier(modifier) { + this.scheduledInstallModifiers.push(modifier); + } + + scheduleUpdateModifier(modifier) { + this.scheduledUpdateModifiers.push(modifier); + } + + commit() { + let { + createdComponents, + updatedComponents + } = this; + + for (let i = 0; i < createdComponents.length; i++) { + let { + manager, + state + } = createdComponents[i]; + manager.didCreate(state); + } + + for (let i = 0; i < updatedComponents.length; i++) { + let { + manager, + state + } = updatedComponents[i]; + manager.didUpdate(state); + } + + let { + scheduledInstallModifiers, + scheduledUpdateModifiers + } = this; // Prevent a transpilation issue we guard against in Ember, the + // throw-if-closure-required issue + + let manager, state; + + for (let i = 0; i < scheduledInstallModifiers.length; i++) { + let modifier = scheduledInstallModifiers[i]; + manager = modifier.manager; + state = modifier.state; + let modifierTag = manager.getTag(state); + + if (modifierTag !== null) { + let tag = track( // eslint-disable-next-line no-loop-func + () => manager.install(state), DEBUG && `- While rendering:\n (instance of a \`${modifier.definition.resolvedName || manager.getDebugName(modifier.definition.state)}\` modifier)`); + updateTag(modifierTag, tag); + } else { + manager.install(state); + } + } + + for (let i = 0; i < scheduledUpdateModifiers.length; i++) { + let modifier = scheduledUpdateModifiers[i]; + manager = modifier.manager; + state = modifier.state; + let modifierTag = manager.getTag(state); + + if (modifierTag !== null) { + let tag = track( // eslint-disable-next-line no-loop-func + () => manager.update(state), DEBUG && `- While rendering:\n (instance of a \`${modifier.definition.resolvedName || manager.getDebugName(modifier.definition.state)}\` modifier)`); + updateTag(modifierTag, tag); + } else { + manager.update(state); + } + } + } + +} + +class EnvironmentImpl { + constructor(options, delegate) { + this.delegate = delegate; + this[_a$1] = null; // Delegate methods and values + + this.isInteractive = this.delegate.isInteractive; + this.debugRenderTree = this.delegate.enableDebugTooling ? new DebugRenderTreeImpl() : undefined; + + if (options.appendOperations) { + this.appendOperations = options.appendOperations; + this.updateOperations = options.updateOperations; + } else if (options.document) { + this.appendOperations = new DOMTreeConstruction(options.document); + this.updateOperations = new DOMChangesImpl(options.document); + } else if (DEBUG) { + throw new Error('you must pass document or appendOperations to a new runtime'); + } + } + + getAppendOperations() { + return this.appendOperations; + } + + getDOM() { + return this.updateOperations; + } + + begin() { + var _b; + (_b = this.debugRenderTree) === null || _b === void 0 ? void 0 : _b.begin(); + this[TRANSACTION] = new TransactionImpl(); + } + + get transaction() { + return this[TRANSACTION]; + } + + didCreate(component) { + this.transaction.didCreate(component); + } + + didUpdate(component) { + this.transaction.didUpdate(component); + } + + scheduleInstallModifier(modifier) { + if (this.isInteractive) { + this.transaction.scheduleInstallModifier(modifier); + } + } + + scheduleUpdateModifier(modifier) { + if (this.isInteractive) { + this.transaction.scheduleUpdateModifier(modifier); + } + } + + commit() { + var _b; + + let transaction = this.transaction; + this[TRANSACTION] = null; + transaction.commit(); + (_b = this.debugRenderTree) === null || _b === void 0 ? void 0 : _b.commit(); + this.delegate.onTransactionCommit(); + } + +} +_a$1 = TRANSACTION; +function runtimeContext(options, delegate, artifacts, resolver) { + return { + env: new EnvironmentImpl(options, delegate), + program: new RuntimeProgramImpl(artifacts.constants, artifacts.heap), + resolver: resolver + }; +} +function inTransaction(env, cb) { + if (!env[TRANSACTION]) { + env.begin(); + + try { + cb(); + } finally { + env.commit(); + } + } else { + cb(); + } +} + +function initializeRegistersWithSP(sp) { + return [0, -1, sp, 0]; +} +class LowLevelVM { + constructor(stack, heap, program, externs, registers) { + this.stack = stack; + this.heap = heap; + this.program = program; + this.externs = externs; + this.registers = registers; + this.currentOpSize = 0; + } + + fetchRegister(register) { + return this.registers[register]; + } + + loadRegister(register, value) { + this.registers[register] = value; + } + + setPc(pc) { + this.registers[$pc] = pc; + } // Start a new frame and save $ra and $fp on the stack + + + pushFrame() { + this.stack.push(this.registers[$ra]); + this.stack.push(this.registers[$fp]); + this.registers[$fp] = this.registers[$sp] - 1; + } // Restore $ra, $sp and $fp + + + popFrame() { + this.registers[$sp] = this.registers[$fp] - 1; + this.registers[$ra] = this.stack.get(0); + this.registers[$fp] = this.stack.get(1); + } + + pushSmallFrame() { + this.stack.push(this.registers[$ra]); + } + + popSmallFrame() { + this.registers[$ra] = this.stack.pop(); + } // Jump to an address in `program` + + + goto(offset) { + this.setPc(this.target(offset)); + } + + target(offset) { + return this.registers[$pc] + offset - this.currentOpSize; + } // Save $pc into $ra, then jump to a new address in `program` (jal in MIPS) + + + call(handle) { + this.registers[$ra] = this.registers[$pc]; + this.setPc(this.heap.getaddr(handle)); + } // Put a specific `program` address in $ra + + + returnTo(offset) { + this.registers[$ra] = this.target(offset); + } // Return to the `program` address stored in $ra + + + return() { + this.setPc(this.registers[$ra]); + } + + nextStatement() { + let { + registers, + program + } = this; + let pc = registers[$pc]; + + if (pc === -1) { + return null; + } // We have to save off the current operations size so that + // when we do a jump we can calculate the correct offset + // to where we are going. We can't simply ask for the size + // in a jump because we have have already incremented the + // program counter to the next instruction prior to executing. + + + let opcode = program.opcode(pc); + let operationSize = this.currentOpSize = opcode.size; + this.registers[$pc] += operationSize; + return opcode; + } + + evaluateOuter(opcode, vm) { + { + this.evaluateInner(opcode, vm); + } + } + + evaluateInner(opcode, vm) { + if (opcode.isMachine) { + this.evaluateMachine(opcode); + } else { + this.evaluateSyscall(opcode, vm); + } + } + + evaluateMachine(opcode) { + switch (opcode.type) { + case 0 + /* PushFrame */ + : + return this.pushFrame(); + + case 1 + /* PopFrame */ + : + return this.popFrame(); + + case 3 + /* InvokeStatic */ + : + return this.call(opcode.op1); + + case 2 + /* InvokeVirtual */ + : + return this.call(this.stack.pop()); + + case 4 + /* Jump */ + : + return this.goto(opcode.op1); + + case 5 + /* Return */ + : + return this.return(); + + case 6 + /* ReturnTo */ + : + return this.returnTo(opcode.op1); + } + } + + evaluateSyscall(opcode, vm) { + APPEND_OPCODES.evaluate(vm, opcode, opcode.type); + } + +} + +class UpdatingVMImpl { + constructor(env, { + alwaysRevalidate = false + }) { + this.frameStack = new Stack(); + this.env = env; + this.dom = env.getDOM(); + this.alwaysRevalidate = alwaysRevalidate; + } + + execute(opcodes, handler) { + if (DEBUG) { + let hasErrored = true; + + try { + runInTrackingTransaction(() => this._execute(opcodes, handler), '- While rendering:'); // using a boolean here to avoid breaking ergonomics of "pause on uncaught exceptions" + // which would happen with a `catch` + `throw` + + hasErrored = false; + } finally { + if (hasErrored) { + // eslint-disable-next-line no-console + console.error(`\n\nError occurred:\n\n${resetTracking()}\n\n`); + } + } + } else { + this._execute(opcodes, handler); + } + } + + _execute(opcodes, handler) { + let { + frameStack + } = this; + this.try(opcodes, handler); + + while (true) { + if (frameStack.isEmpty()) break; + let opcode = this.frame.nextStatement(); + + if (opcode === undefined) { + frameStack.pop(); + continue; + } + + opcode.evaluate(this); + } + } + + get frame() { + return this.frameStack.current; + } + + goto(index) { + this.frame.goto(index); + } + + try(ops, handler) { + this.frameStack.push(new UpdatingVMFrame(ops, handler)); + } + + throw() { + this.frame.handleException(); + this.frameStack.pop(); + } + +} +class ResumableVMStateImpl { + constructor(state, resumeCallback) { + this.state = state; + this.resumeCallback = resumeCallback; + } + + resume(runtime, builder) { + return this.resumeCallback(runtime, this.state, builder); + } + +} +class BlockOpcode { + constructor(state, runtime, bounds, children) { + this.state = state; + this.runtime = runtime; + this.children = children; + this.bounds = bounds; + } + + parentElement() { + return this.bounds.parentElement(); + } + + firstNode() { + return this.bounds.firstNode(); + } + + lastNode() { + return this.bounds.lastNode(); + } + + evaluate(vm) { + vm.try(this.children, null); + } + +} +class TryOpcode extends BlockOpcode { + constructor() { + super(...arguments); + this.type = 'try'; + } + + evaluate(vm) { + vm.try(this.children, this); + } + + handleException() { + let { + state, + bounds, + runtime + } = this; + destroyChildren(this); + let elementStack = NewElementBuilder.resume(runtime.env, bounds); + let vm = state.resume(runtime, elementStack); + let updating = []; + let children = this.children = []; + let result = vm.execute(vm => { + vm.pushUpdating(updating); + vm.updateWith(this); + vm.pushUpdating(children); + }); + associateDestroyableChild(this, result.drop); + } + +} +class ListItemOpcode extends TryOpcode { + constructor(state, runtime, bounds, key, memo, value) { + super(state, runtime, bounds, []); + this.key = key; + this.memo = memo; + this.value = value; + this.retained = false; + this.index = -1; + } + + updateReferences(item) { + this.retained = true; + updateRef(this.value, item.value); + updateRef(this.memo, item.memo); + } + + shouldRemove() { + return !this.retained; + } + + reset() { + this.retained = false; + } + +} +class ListBlockOpcode extends BlockOpcode { + constructor(state, runtime, bounds, children, iterableRef) { + super(state, runtime, bounds, children); + this.iterableRef = iterableRef; + this.type = 'list-block'; + this.opcodeMap = new Map(); + this.marker = null; + this.lastIterator = valueForRef(iterableRef); + } + + initializeChild(opcode) { + opcode.index = this.children.length - 1; + this.opcodeMap.set(opcode.key, opcode); + } + + evaluate(vm) { + let iterator = valueForRef(this.iterableRef); + + if (this.lastIterator !== iterator) { + let { + bounds + } = this; + let { + dom + } = vm; + let marker = this.marker = dom.createComment(''); + dom.insertAfter(bounds.parentElement(), marker, bounds.lastNode()); + this.sync(iterator); + this.parentElement().removeChild(marker); + this.marker = null; + this.lastIterator = iterator; + } // Run now-updated updating opcodes + + + super.evaluate(vm); + } + + sync(iterator) { + let { + opcodeMap: itemMap, + children + } = this; + let currentOpcodeIndex = 0; + let seenIndex = 0; + this.children = this.bounds.boundList = []; + + while (true) { + let item = iterator.next(); + if (item === null) break; + let opcode = children[currentOpcodeIndex]; + let { + key + } = item; // Items that have already been found and moved will already be retained, + // we can continue until we find the next unretained item + + while (opcode !== undefined && opcode.retained === true) { + opcode = children[++currentOpcodeIndex]; + } + + if (opcode !== undefined && opcode.key === key) { + this.retainItem(opcode, item); + currentOpcodeIndex++; + } else if (itemMap.has(key)) { + let itemOpcode = itemMap.get(key); // The item opcode was seen already, so we should move it. + + if (itemOpcode.index < seenIndex) { + this.moveItem(itemOpcode, item, opcode); + } else { + // Update the seen index, we are going to be moving this item around + // so any other items that come before it will likely need to move as + // well. + seenIndex = itemOpcode.index; + let seenUnretained = false; // iterate through all of the opcodes between the current position and + // the position of the item's opcode, and determine if they are all + // retained. + + for (let i = currentOpcodeIndex + 1; i < seenIndex; i++) { + if (children[i].retained === false) { + seenUnretained = true; + break; + } + } // If we have seen only retained opcodes between this and the matching + // opcode, it means that all the opcodes in between have been moved + // already, and we can safely retain this item's opcode. + + + if (seenUnretained === false) { + this.retainItem(itemOpcode, item); + currentOpcodeIndex = seenIndex + 1; + } else { + this.moveItem(itemOpcode, item, opcode); + currentOpcodeIndex++; + } + } + } else { + this.insertItem(item, opcode); + } + } + + for (let i = 0; i < children.length; i++) { + let opcode = children[i]; + + if (opcode.retained === false) { + this.deleteItem(opcode); + } else { + opcode.reset(); + } + } + } + + retainItem(opcode, item) { + + let { + children + } = this; + updateRef(opcode.memo, item.memo); + updateRef(opcode.value, item.value); + opcode.retained = true; + opcode.index = children.length; + children.push(opcode); + } + + insertItem(item, before) { + + let { + opcodeMap, + bounds, + state, + runtime, + children + } = this; + let { + key + } = item; + let nextSibling = before === undefined ? this.marker : before.firstNode(); + let elementStack = NewElementBuilder.forInitialRender(runtime.env, { + element: bounds.parentElement(), + nextSibling + }); + let vm = state.resume(runtime, elementStack); + vm.execute(vm => { + vm.pushUpdating(); + let opcode = vm.enterItem(item); + opcode.index = children.length; + children.push(opcode); + opcodeMap.set(key, opcode); + associateDestroyableChild(this, opcode); + }); + } + + moveItem(opcode, item, before) { + let { + children + } = this; + updateRef(opcode.memo, item.memo); + updateRef(opcode.value, item.value); + opcode.retained = true; + let currentSibling, nextSibling; + + if (before === undefined) { + move(opcode, this.marker); + } else { + currentSibling = opcode.lastNode().nextSibling; + nextSibling = before.firstNode(); // Items are moved throughout the algorithm, so there are cases where the + // the items already happen to be siblings (e.g. an item in between was + // moved before this move happened). Check to see if they are siblings + // first before doing the move. + + if (currentSibling !== nextSibling) { + move(opcode, nextSibling); + } + } + + opcode.index = children.length; + children.push(opcode); + } + + deleteItem(opcode) { + + destroy(opcode); + clear(opcode); + this.opcodeMap.delete(opcode.key); + } + +} + +class UpdatingVMFrame { + constructor(ops, exceptionHandler) { + this.ops = ops; + this.exceptionHandler = exceptionHandler; + this.current = 0; + } + + goto(index) { + this.current = index; + } + + nextStatement() { + return this.ops[this.current++]; + } + + handleException() { + if (this.exceptionHandler) { + this.exceptionHandler.handleException(); + } + } + +} + +class RenderResultImpl { + constructor(env, updating, bounds, drop) { + this.env = env; + this.updating = updating; + this.bounds = bounds; + this.drop = drop; + associateDestroyableChild(this, drop); + registerDestructor(this, () => clear(this.bounds)); + } + + rerender({ + alwaysRevalidate = false + } = { + alwaysRevalidate: false + }) { + let { + env, + updating + } = this; + let vm = new UpdatingVMImpl(env, { + alwaysRevalidate + }); + vm.execute(updating, this); + } + + parentElement() { + return this.bounds.parentElement(); + } + + firstNode() { + return this.bounds.firstNode(); + } + + lastNode() { + return this.bounds.lastNode(); + } + + handleException() { + throw 'this should never happen'; + } + +} + +class EvaluationStackImpl { + // fp -> sp + constructor(stack = [], registers) { + this.stack = stack; + this[REGISTERS] = registers; + } + + static restore(snapshot) { + return new this(snapshot.slice(), initializeRegistersWithSP(snapshot.length - 1)); + } + + push(value) { + this.stack[++this[REGISTERS][$sp]] = value; + } + + dup(position = this[REGISTERS][$sp]) { + this.stack[++this[REGISTERS][$sp]] = this.stack[position]; + } + + copy(from, to) { + this.stack[to] = this.stack[from]; + } + + pop(n = 1) { + let top = this.stack[this[REGISTERS][$sp]]; + this[REGISTERS][$sp] -= n; + return top; + } + + peek(offset = 0) { + return this.stack[this[REGISTERS][$sp] - offset]; + } + + get(offset, base = this[REGISTERS][$fp]) { + return this.stack[base + offset]; + } + + set(value, offset, base = this[REGISTERS][$fp]) { + this.stack[base + offset] = value; + } + + slice(start, end) { + return this.stack.slice(start, end); + } + + capture(items) { + let end = this[REGISTERS][$sp] + 1; + let start = end - items; + return this.stack.slice(start, end); + } + + reset() { + this.stack.length = 0; + } + + toArray() { + return this.stack.slice(this[REGISTERS][$fp], this[REGISTERS][$sp] + 1); + } + +} + +var _a$2, _b; + +class Stacks { + constructor() { + this.scope = new Stack(); + this.dynamicScope = new Stack(); + this.updating = new Stack(); + this.cache = new Stack(); + this.list = new Stack(); + } + +} + +class VM { + /** + * End of migrated. + */ + constructor(runtime, { + pc, + scope, + dynamicScope, + stack + }, elementStack, context) { + this.runtime = runtime; + this.elementStack = elementStack; + this.context = context; + this[_a$2] = new Stacks(); + this[_b] = new Stack(); + this.s0 = null; + this.s1 = null; + this.t0 = null; + this.t1 = null; + this.v0 = null; + this.resume = initVM(this.context); + + if (DEBUG) { + assertGlobalContextWasSet(); + } + + let evalStack = EvaluationStackImpl.restore(stack); + evalStack[REGISTERS][$pc] = pc; + evalStack[REGISTERS][$sp] = stack.length - 1; + evalStack[REGISTERS][$fp] = -1; + this[HEAP] = this.program.heap; + this[CONSTANTS] = this.program.constants; + this.elementStack = elementStack; + this[STACKS].scope.push(scope); + this[STACKS].dynamicScope.push(dynamicScope); + this[ARGS] = new VMArgumentsImpl(); + this[INNER_VM] = new LowLevelVM(evalStack, this[HEAP], runtime.program, { + debugBefore: opcode => { + return APPEND_OPCODES.debugBefore(this, opcode); + }, + debugAfter: state => { + APPEND_OPCODES.debugAfter(this, state); + } + }, evalStack[REGISTERS]); + this.destructor = {}; + this[DESTROYABLE_STACK].push(this.destructor); + } + + get stack() { + return this[INNER_VM].stack; + } + /* Registers */ + + + get pc() { + return this[INNER_VM].fetchRegister($pc); + } // Fetch a value from a register onto the stack + + + fetch(register) { + let value = this.fetchValue(register); + this.stack.push(value); + } // Load a value from the stack into a register + + + load(register) { + let value = this.stack.pop(); + this.loadValue(register, value); + } + + fetchValue(register) { + if (isLowLevelRegister(register)) { + return this[INNER_VM].fetchRegister(register); + } + + switch (register) { + case $s0: + return this.s0; + + case $s1: + return this.s1; + + case $t0: + return this.t0; + + case $t1: + return this.t1; + + case $v0: + return this.v0; + } + } // Load a value into a register + + + loadValue(register, value) { + if (isLowLevelRegister(register)) { + this[INNER_VM].loadRegister(register, value); + } + + switch (register) { + case $s0: + this.s0 = value; + break; + + case $s1: + this.s1 = value; + break; + + case $t0: + this.t0 = value; + break; + + case $t1: + this.t1 = value; + break; + + case $v0: + this.v0 = value; + break; + } + } + /** + * Migrated to Inner + */ + // Start a new frame and save $ra and $fp on the stack + + + pushFrame() { + this[INNER_VM].pushFrame(); + } // Restore $ra, $sp and $fp + + + popFrame() { + this[INNER_VM].popFrame(); + } // Jump to an address in `program` + + + goto(offset) { + this[INNER_VM].goto(offset); + } // Save $pc into $ra, then jump to a new address in `program` (jal in MIPS) + + + call(handle) { + this[INNER_VM].call(handle); + } // Put a specific `program` address in $ra + + + returnTo(offset) { + this[INNER_VM].returnTo(offset); + } // Return to the `program` address stored in $ra + + + return() { + this[INNER_VM].return(); + } + + static initial(runtime, context, { + handle, + self, + dynamicScope, + treeBuilder, + numSymbols, + owner + }) { + let scope = PartialScopeImpl.root(self, numSymbols, owner); + let state = vmState(runtime.program.heap.getaddr(handle), scope, dynamicScope); + let vm = initVM(context)(runtime, state, treeBuilder); + vm.pushUpdating(); + return vm; + } + + static empty(runtime, { + handle, + treeBuilder, + dynamicScope, + owner + }, context) { + let vm = initVM(context)(runtime, vmState(runtime.program.heap.getaddr(handle), PartialScopeImpl.root(UNDEFINED_REFERENCE, 0, owner), dynamicScope), treeBuilder); + vm.pushUpdating(); + return vm; + } + + compile(block) { + let handle = unwrapHandle(block.compile(this.context)); + return handle; + } + + get program() { + return this.runtime.program; + } + + get env() { + return this.runtime.env; + } + + captureState(args, pc = this[INNER_VM].fetchRegister($pc)) { + return { + pc, + scope: this.scope(), + dynamicScope: this.dynamicScope(), + stack: this.stack.capture(args) + }; + } + + capture(args, pc = this[INNER_VM].fetchRegister($pc)) { + return new ResumableVMStateImpl(this.captureState(args, pc), this.resume); + } + + beginCacheGroup(name) { + let opcodes = this.updating(); + let guard = new JumpIfNotModifiedOpcode(); + opcodes.push(guard); + opcodes.push(new BeginTrackFrameOpcode(name)); + this[STACKS].cache.push(guard); + beginTrackFrame(name); + } + + commitCacheGroup() { + let opcodes = this.updating(); + let guard = this[STACKS].cache.pop(); + let tag = endTrackFrame(); + opcodes.push(new EndTrackFrameOpcode(guard)); + guard.finalize(tag, opcodes.length); + } + + enter(args) { + let updating = []; + let state = this.capture(args); + let block = this.elements().pushUpdatableBlock(); + let tryOpcode = new TryOpcode(state, this.runtime, block, updating); + this.didEnter(tryOpcode); + } + + enterItem({ + key, + value, + memo + }) { + let { + stack + } = this; + let valueRef = createIteratorItemRef(value); + let memoRef = createIteratorItemRef(memo); + stack.push(valueRef); + stack.push(memoRef); + let state = this.capture(2); + let block = this.elements().pushUpdatableBlock(); + let opcode = new ListItemOpcode(state, this.runtime, block, key, memoRef, valueRef); + this.didEnter(opcode); + return opcode; + } + + registerItem(opcode) { + this.listBlock().initializeChild(opcode); + } + + enterList(iterableRef, offset) { + let updating = []; + let addr = this[INNER_VM].target(offset); + let state = this.capture(0, addr); + let list = this.elements().pushBlockList(updating); + let opcode = new ListBlockOpcode(state, this.runtime, list, updating, iterableRef); + this[STACKS].list.push(opcode); + this.didEnter(opcode); + } + + didEnter(opcode) { + this.associateDestroyable(opcode); + this[DESTROYABLE_STACK].push(opcode); + this.updateWith(opcode); + this.pushUpdating(opcode.children); + } + + exit() { + this[DESTROYABLE_STACK].pop(); + this.elements().popBlock(); + this.popUpdating(); + } + + exitList() { + this.exit(); + this[STACKS].list.pop(); + } + + pushUpdating(list = []) { + this[STACKS].updating.push(list); + } + + popUpdating() { + return this[STACKS].updating.pop(); + } + + updateWith(opcode) { + this.updating().push(opcode); + } + + listBlock() { + return this[STACKS].list.current; + } + + associateDestroyable(child) { + let parent = this[DESTROYABLE_STACK].current; + associateDestroyableChild(parent, child); + } + + tryUpdating() { + return this[STACKS].updating.current; + } + + updating() { + return this[STACKS].updating.current; + } + + elements() { + return this.elementStack; + } + + scope() { + return this[STACKS].scope.current; + } + + dynamicScope() { + return this[STACKS].dynamicScope.current; + } + + pushChildScope() { + this[STACKS].scope.push(this.scope().child()); + } + + pushDynamicScope() { + let child = this.dynamicScope().child(); + this[STACKS].dynamicScope.push(child); + return child; + } + + pushRootScope(size, owner) { + let scope = PartialScopeImpl.sized(size, owner); + this[STACKS].scope.push(scope); + return scope; + } + + pushScope(scope) { + this[STACKS].scope.push(scope); + } + + popScope() { + this[STACKS].scope.pop(); + } + + popDynamicScope() { + this[STACKS].dynamicScope.pop(); + } /// SCOPE HELPERS + + + getOwner() { + return this.scope().owner; + } + + getSelf() { + return this.scope().getSelf(); + } + + referenceForSymbol(symbol$$1) { + return this.scope().getSymbol(symbol$$1); + } /// EXECUTION + + + execute(initialize) { + if (DEBUG) { + let hasErrored = true; + + try { + let value = this._execute(initialize); // using a boolean here to avoid breaking ergonomics of "pause on uncaught exceptions" + // which would happen with a `catch` + `throw` + + + hasErrored = false; + return value; + } finally { + if (hasErrored) { + // If any existing blocks are open, due to an error or something like + // that, we need to close them all and clean things up properly. + let elements = this.elements(); + + while (elements.hasBlocks) { + elements.popBlock(); + } // eslint-disable-next-line no-console + + + console.error(`\n\nError occurred:\n\n${resetTracking()}\n\n`); + } + } + } else { + return this._execute(initialize); + } + } + + _execute(initialize) { + + if (initialize) initialize(this); + let result; + + while (true) { + result = this.next(); + if (result.done) break; + } + + return result.value; + } + + next() { + let { + env, + elementStack + } = this; + let opcode = this[INNER_VM].nextStatement(); + let result; + + if (opcode !== null) { + this[INNER_VM].evaluateOuter(opcode, this); + result = { + done: false, + value: null + }; + } else { + // Unload the stack + this.stack.reset(); + result = { + done: true, + value: new RenderResultImpl(env, this.popUpdating(), elementStack.popBlock(), this.destructor) + }; + } + + return result; + } + + bindDynamicScope(names) { + let scope = this.dynamicScope(); + + for (let i = names.length - 1; i >= 0; i--) { + let name = names[i]; + scope.set(name, this.stack.pop()); + } + } + +} +_a$2 = STACKS, _b = DESTROYABLE_STACK; + +function vmState(pc, scope, dynamicScope) { + return { + pc, + scope, + dynamicScope, + stack: [] + }; +} + +function initVM(context) { + return (runtime, state, builder) => new VM(runtime, state, builder, context); +} + +class TemplateIteratorImpl { + constructor(vm) { + this.vm = vm; + } + + next() { + return this.vm.next(); + } + + sync() { + if (DEBUG) { + return runInTrackingTransaction(() => this.vm.execute(), '- While rendering:'); + } else { + return this.vm.execute(); + } + } + +} + +function renderSync(env, iterator) { + let result; + inTransaction(env, () => result = iterator.sync()); + return result; +} +function renderMain(runtime, context, owner, self, treeBuilder, layout, dynamicScope = new DynamicScopeImpl()) { + let handle = unwrapHandle(layout.compile(context)); + let numSymbols = layout.symbolTable.symbols.length; + let vm = VM.initial(runtime, context, { + self, + dynamicScope, + treeBuilder, + handle, + numSymbols, + owner + }); + return new TemplateIteratorImpl(vm); +} + +function renderInvocation(vm, context, owner, definition, args) { + // Get a list of tuples of argument names and references, like + // [['title', reference], ['name', reference]] + const argList = Object.keys(args).map(key => [key, args[key]]); + const blockNames = ['main', 'else', 'attrs']; // Prefix argument names with `@` symbol + + const argNames = argList.map(([name]) => `@${name}`); + let reified = vm[CONSTANTS].component(definition, owner); + vm.pushFrame(); // Push blocks on to the stack, three stack values per block + + for (let i = 0; i < 3 * blockNames.length; i++) { + vm.stack.push(null); + } + + vm.stack.push(null); // For each argument, push its backing reference on to the stack + + argList.forEach(([, reference]) => { + vm.stack.push(reference); + }); // Configure VM based on blocks and args just pushed on to the stack. + + vm[ARGS].setup(vm.stack, argNames, blockNames, 0, true); + const compilable = reified.compilable; + const layoutHandle = unwrapHandle(compilable.compile(context)); + const invocation = { + handle: layoutHandle, + symbolTable: compilable.symbolTable + }; // Needed for the Op.Main opcode: arguments, component invocation object, and + // component definition. + + vm.stack.push(vm[ARGS]); + vm.stack.push(invocation); + vm.stack.push(reified); + return new TemplateIteratorImpl(vm); +} + +function renderComponent(runtime, treeBuilder, context, owner, definition, args = {}, dynamicScope = new DynamicScopeImpl()) { + let vm = VM.empty(runtime, { + treeBuilder, + handle: context.stdlib.main, + dynamicScope, + owner + }, context); + return renderInvocation(vm, context, owner, definition, recordToReference(args)); +} + +function recordToReference(record) { + const root = createConstRef(record, 'args'); + return Object.keys(record).reduce((acc, key) => { + acc[key] = childRefFor(root, key); + return acc; + }, {}); +} + +const SERIALIZATION_FIRST_NODE_STRING = '%+b:0%'; +function isSerializationFirstNode(node) { + return node.nodeValue === SERIALIZATION_FIRST_NODE_STRING; +} +class RehydratingCursor extends CursorImpl { + constructor(element, nextSibling, startingBlockDepth) { + super(element, nextSibling); + this.startingBlockDepth = startingBlockDepth; + this.candidate = null; + this.injectedOmittedNode = false; + this.openBlockDepth = startingBlockDepth - 1; + } + +} +class RehydrateBuilder extends NewElementBuilder { + constructor(env, parentNode, nextSibling) { + super(env, parentNode, nextSibling); + this.unmatchedAttributes = null; + this.blockDepth = 0; + if (nextSibling) throw new Error('Rehydration with nextSibling not supported'); + let node = this.currentCursor.element.firstChild; + + while (node !== null) { + if (isOpenBlock(node)) { + break; + } + + node = node.nextSibling; + } + this.candidate = node; + const startingBlockOffset = getBlockDepth(node); + + if (startingBlockOffset !== 0) { + // We are rehydrating from a partial tree and not the root component + // We need to add an extra block before the first block to rehydrate correctly + // The extra block is needed since the renderComponent API creates a synthetic component invocation which generates the extra block + const newBlockDepth = startingBlockOffset - 1; + const newCandidate = this.dom.createComment(`%+b:${newBlockDepth}%`); + node.parentNode.insertBefore(newCandidate, this.candidate); + let closingNode = node.nextSibling; + + while (closingNode !== null) { + if (isCloseBlock(closingNode) && getBlockDepth(closingNode) === startingBlockOffset) { + break; + } + + closingNode = closingNode.nextSibling; + } + const newClosingBlock = this.dom.createComment(`%-b:${newBlockDepth}%`); + node.parentNode.insertBefore(newClosingBlock, closingNode.nextSibling); + this.candidate = newCandidate; + this.startingBlockOffset = newBlockDepth; + } else { + this.startingBlockOffset = 0; + } + } + + get currentCursor() { + return this[CURSOR_STACK].current; + } + + get candidate() { + if (this.currentCursor) { + return this.currentCursor.candidate; + } + + return null; + } + + set candidate(node) { + let currentCursor = this.currentCursor; + currentCursor.candidate = node; + } + + disableRehydration(nextSibling) { + let currentCursor = this.currentCursor; // rehydration will be disabled until we either: + // * hit popElement (and return to using the parent elements cursor) + // * hit closeBlock and the next sibling is a close block comment + // matching the expected openBlockDepth + + currentCursor.candidate = null; + currentCursor.nextSibling = nextSibling; + } + + enableRehydration(candidate) { + let currentCursor = this.currentCursor; + currentCursor.candidate = candidate; + currentCursor.nextSibling = null; + } + + pushElement(element, nextSibling = null) { + let cursor = new RehydratingCursor(element, nextSibling, this.blockDepth || 0); + /** + *
<--------------- currentCursor.element + * <------- would have been removed during openBlock + *
<--------------- currentCursor.candidate -> cursor.element + * <----- currentCursor.candidate.firstChild -> cursor.candidate + * Foo + * + *
+ * <------ becomes currentCursor.candidate + */ + + if (this.candidate !== null) { + cursor.candidate = element.firstChild; + this.candidate = element.nextSibling; + } + + this[CURSOR_STACK].push(cursor); + } // clears until the end of the current container + // either the current open block or higher + + + clearMismatch(candidate) { + let current = candidate; + let currentCursor = this.currentCursor; + + if (currentCursor !== null) { + let openBlockDepth = currentCursor.openBlockDepth; + + if (openBlockDepth >= currentCursor.startingBlockDepth) { + while (current) { + if (isCloseBlock(current)) { + let closeBlockDepth = getBlockDepthWithOffset(current, this.startingBlockOffset); + + if (openBlockDepth >= closeBlockDepth) { + break; + } + } + + current = this.remove(current); + } + } else { + while (current !== null) { + current = this.remove(current); + } + } // current cursor parentNode should be openCandidate if element + // or openCandidate.parentNode if comment + + + this.disableRehydration(current); + } + } + + __openBlock() { + let { + currentCursor + } = this; + if (currentCursor === null) return; + let blockDepth = this.blockDepth; + this.blockDepth++; + let { + candidate + } = currentCursor; + if (candidate === null) return; + let { + tagName + } = currentCursor.element; + + if (isOpenBlock(candidate) && getBlockDepthWithOffset(candidate, this.startingBlockOffset) === blockDepth) { + this.candidate = this.remove(candidate); + currentCursor.openBlockDepth = blockDepth; + } else if (tagName !== 'TITLE' && tagName !== 'SCRIPT' && tagName !== 'STYLE') { + this.clearMismatch(candidate); + } + } + + __closeBlock() { + let { + currentCursor + } = this; + if (currentCursor === null) return; // openBlock is the last rehydrated open block + + let openBlockDepth = currentCursor.openBlockDepth; // this currently is the expected next open block depth + + this.blockDepth--; + let { + candidate + } = currentCursor; + let isRehydrating = false; + + if (candidate !== null) { + isRehydrating = true; //assert( + // openBlockDepth === this.blockDepth, + // 'when rehydrating, openBlockDepth should match this.blockDepth here' + //); + + if (isCloseBlock(candidate) && getBlockDepthWithOffset(candidate, this.startingBlockOffset) === openBlockDepth) { + let nextSibling = this.remove(candidate); + this.candidate = nextSibling; + currentCursor.openBlockDepth--; + } else { + // close the block and clear mismatch in parent container + // we will be either at the end of the element + // or at the end of our containing block + this.clearMismatch(candidate); + isRehydrating = false; + } + } + + if (isRehydrating === false) { + // check if nextSibling matches our expected close block + // if so, we remove the close block comment and + // restore rehydration after clearMismatch disabled + let nextSibling = currentCursor.nextSibling; + + if (nextSibling !== null && isCloseBlock(nextSibling) && getBlockDepthWithOffset(nextSibling, this.startingBlockOffset) === this.blockDepth) { + // restore rehydration state + let candidate = this.remove(nextSibling); + this.enableRehydration(candidate); + currentCursor.openBlockDepth--; + } + } + } + + __appendNode(node) { + let { + candidate + } = this; // This code path is only used when inserting precisely one node. It needs more + // comparison logic, but we can probably lean on the cases where this code path + // is actually used. + + if (candidate) { + return candidate; + } else { + return super.__appendNode(node); + } + } + + __appendHTML(html) { + let candidateBounds = this.markerBounds(); + + if (candidateBounds) { + let first = candidateBounds.firstNode(); + let last = candidateBounds.lastNode(); + let newBounds = new ConcreteBounds(this.element, first.nextSibling, last.previousSibling); + let possibleEmptyMarker = this.remove(first); + this.remove(last); + + if (possibleEmptyMarker !== null && isEmpty$1(possibleEmptyMarker)) { + this.candidate = this.remove(possibleEmptyMarker); + + if (this.candidate !== null) { + this.clearMismatch(this.candidate); + } + } + + return newBounds; + } else { + return super.__appendHTML(html); + } + } + + remove(node) { + let element = node.parentNode; + let next = node.nextSibling; + element.removeChild(node); + return next; + } + + markerBounds() { + let _candidate = this.candidate; + + if (_candidate && isMarker(_candidate)) { + let first = _candidate; + let last = first.nextSibling; + + while (last && !isMarker(last)) { + last = last.nextSibling; + } + + return new ConcreteBounds(this.element, first, last); + } else { + return null; + } + } + + __appendText(string) { + let { + candidate + } = this; + + if (candidate) { + if (isTextNode(candidate)) { + if (candidate.nodeValue !== string) { + candidate.nodeValue = string; + } + + this.candidate = candidate.nextSibling; + return candidate; + } else if (isSeparator(candidate)) { + this.candidate = this.remove(candidate); + return this.__appendText(string); + } else if (isEmpty$1(candidate) && string === '') { + this.candidate = this.remove(candidate); + return this.__appendText(string); + } else { + this.clearMismatch(candidate); + return super.__appendText(string); + } + } else { + return super.__appendText(string); + } + } + + __appendComment(string) { + let _candidate = this.candidate; + + if (_candidate && isComment(_candidate)) { + if (_candidate.nodeValue !== string) { + _candidate.nodeValue = string; + } + + this.candidate = _candidate.nextSibling; + return _candidate; + } else if (_candidate) { + this.clearMismatch(_candidate); + } + + return super.__appendComment(string); + } + + __openElement(tag) { + let _candidate = this.candidate; + + if (_candidate && isElement(_candidate) && isSameNodeType(_candidate, tag)) { + this.unmatchedAttributes = [].slice.call(_candidate.attributes); + return _candidate; + } else if (_candidate) { + if (isElement(_candidate) && _candidate.tagName === 'TBODY') { + this.pushElement(_candidate, null); + this.currentCursor.injectedOmittedNode = true; + return this.__openElement(tag); + } + + this.clearMismatch(_candidate); + } + + return super.__openElement(tag); + } + + __setAttribute(name, value, namespace) { + let unmatched = this.unmatchedAttributes; + + if (unmatched) { + let attr = findByName(unmatched, name); + + if (attr) { + if (attr.value !== value) { + attr.value = value; + } + + unmatched.splice(unmatched.indexOf(attr), 1); + return; + } + } + + return super.__setAttribute(name, value, namespace); + } + + __setProperty(name, value) { + let unmatched = this.unmatchedAttributes; + + if (unmatched) { + let attr = findByName(unmatched, name); + + if (attr) { + if (attr.value !== value) { + attr.value = value; + } + + unmatched.splice(unmatched.indexOf(attr), 1); + return; + } + } + + return super.__setProperty(name, value); + } + + __flushElement(parent, constructing) { + let { + unmatchedAttributes: unmatched + } = this; + + if (unmatched) { + for (let i = 0; i < unmatched.length; i++) { + this.constructing.removeAttribute(unmatched[i].name); + } + + this.unmatchedAttributes = null; + } else { + super.__flushElement(parent, constructing); + } + } + + willCloseElement() { + let { + candidate, + currentCursor + } = this; + + if (candidate !== null) { + this.clearMismatch(candidate); + } + + if (currentCursor && currentCursor.injectedOmittedNode) { + this.popElement(); + } + + super.willCloseElement(); + } + + getMarker(element, guid) { + let marker = element.querySelector(`script[glmr="${guid}"]`); + + if (marker) { + return marker; + } + + return null; + } + + __pushRemoteElement(element, cursorId, insertBefore) { + let marker = this.getMarker(element, cursorId); + + if (insertBefore === undefined) { + while (element.firstChild !== null && element.firstChild !== marker) { + this.remove(element.firstChild); + } + + insertBefore = null; + } + + let cursor = new RehydratingCursor(element, null, this.blockDepth); + this[CURSOR_STACK].push(cursor); + + if (marker === null) { + this.disableRehydration(insertBefore); + } else { + this.candidate = this.remove(marker); + } + + let block = new RemoteLiveBlock(element); + return this.pushLiveBlock(block, true); + } + + didAppendBounds(bounds) { + super.didAppendBounds(bounds); + + if (this.candidate) { + let last = bounds.lastNode(); + this.candidate = last && last.nextSibling; + } + + return bounds; + } + +} + +function isTextNode(node) { + return node.nodeType === 3; +} + +function isComment(node) { + return node.nodeType === 8; +} + +function isOpenBlock(node) { + return node.nodeType === 8 + /* COMMENT_NODE */ + && node.nodeValue.lastIndexOf('%+b:', 0) === 0; +} + +function isCloseBlock(node) { + return node.nodeType === 8 + /* COMMENT_NODE */ + && node.nodeValue.lastIndexOf('%-b:', 0) === 0; +} + +function getBlockDepth(node) { + return parseInt(node.nodeValue.slice(4), 10); +} + +function getBlockDepthWithOffset(node, offset) { + return getBlockDepth(node) - offset; +} + +function isElement(node) { + return node.nodeType === 1; +} + +function isMarker(node) { + return node.nodeType === 8 && node.nodeValue === '%glmr%'; +} + +function isSeparator(node) { + return node.nodeType === 8 && node.nodeValue === '%|%'; +} + +function isEmpty$1(node) { + return node.nodeType === 8 && node.nodeValue === '% %'; +} + +function isSameNodeType(candidate, tag) { + if (candidate.namespaceURI === "http://www.w3.org/2000/svg" + /* SVG */ + ) { + return candidate.tagName === tag; + } + + return candidate.tagName === tag.toUpperCase(); +} + +function findByName(array, name) { + for (let i = 0; i < array.length; i++) { + let attr = array[i]; + if (attr.name === name) return attr; + } + + return undefined; +} + +function rehydrationBuilder(env, cursor) { + return RehydrateBuilder.forInitialRender(env, cursor); +} + +let ARGS_CACHES = DEBUG ? new WeakMap() : undefined; + +function getArgs(proxy) { + return getValue(DEBUG ? ARGS_CACHES.get(proxy) : proxy.argsCache); +} + +class SimpleArgsProxy { + constructor(context, computeArgs = () => EMPTY_ARGS) { + let argsCache = createCache(() => computeArgs(context)); + + if (DEBUG) { + ARGS_CACHES.set(this, argsCache); + Object.freeze(this); + } else { + this.argsCache = argsCache; + } + } + + get named() { + return getArgs(this).named || EMPTY_NAMED; + } + + get positional() { + return getArgs(this).positional || EMPTY_POSITIONAL; + } + +} //////////// + + +function invokeHelper(context, definition, computeArgs) { + if (DEBUG && (typeof context !== 'object' || context === null)) { + throw new Error(`Expected a context object to be passed as the first parameter to invokeHelper, got ${context}`); + } + + const owner = getOwner(context); + const internalManager = getInternalHelperManager(definition); // TODO: figure out why assert isn't using the TS assert thing + + if (DEBUG && !internalManager) { + throw new Error(`Expected a helper definition to be passed as the second parameter to invokeHelper, but no helper manager was found. The definition value that was passed was \`${debugToString(definition)}\`. Did you use setHelperManager to associate a helper manager with this value?`); + } + + if (DEBUG && typeof internalManager === 'function') { + throw new Error('Found a helper manager, but it was an internal built-in helper manager. `invokeHelper` does not support internal helpers yet.'); + } + + const manager = internalManager.getDelegateFor(owner); + let args = new SimpleArgsProxy(context, computeArgs); + let bucket = manager.createHelper(definition, args); + let cache; + + if (hasValue(manager)) { + cache = createCache(() => { + if (DEBUG && (isDestroying(cache) || isDestroyed(cache))) { + throw new Error(`You attempted to get the value of a helper after the helper was destroyed, which is not allowed`); + } + + return manager.getValue(bucket); + }); + associateDestroyableChild(context, cache); + } else { + throw new Error('TODO: unreachable, to be implemented with hasScheduledEffect'); + } + + if (hasDestroyable(manager)) { + let destroyable = manager.getDestroyable(bucket); + associateDestroyableChild(cache, destroyable); + } + + return cache; +} + +function internalHelper(helper) { + return setInternalHelperManager(helper, {}); +} + +const context = buildUntouchableThis('`fn` helper'); +/** + The `fn` helper allows you to ensure a function that you are passing off + to another component, helper, or modifier has access to arguments that are + available in the template. + + For example, if you have an `each` helper looping over a number of items, you + may need to pass a function that expects to receive the item as an argument + to a component invoked within the loop. Here's how you could use the `fn` + helper to pass both the function and its arguments together: + + ```app/templates/components/items-listing.hbs + {{#each @items as |item|}} + + {{/each}} + ``` + + ```app/components/items-list.js + import Component from '@glimmer/component'; + import { action } from '@ember/object'; + + export default class ItemsList extends Component { + handleSelected = (item) => { + // ...snip... + } + } + ``` + + In this case the `display-item` component will receive a normal function + that it can invoke. When it invokes the function, the `handleSelected` + function will receive the `item` and any arguments passed, thanks to the + `fn` helper. + + Let's take look at what that means in a couple circumstances: + + - When invoked as `this.args.select()` the `handleSelected` function will + receive the `item` from the loop as its first and only argument. + - When invoked as `this.args.select('foo')` the `handleSelected` function + will receive the `item` from the loop as its first argument and the + string `'foo'` as its second argument. + + In the example above, we used an arrow function to ensure that + `handleSelected` is properly bound to the `items-list`, but let's explore what + happens if we left out the arrow function: + + ```app/components/items-list.js + import Component from '@glimmer/component'; + + export default class ItemsList extends Component { + handleSelected(item) { + // ...snip... + } + } + ``` + + In this example, when `handleSelected` is invoked inside the `display-item` + component, it will **not** have access to the component instance. In other + words, it will have no `this` context, so please make sure your functions + are bound (via an arrow function or other means) before passing into `fn`! + + See also [partial application](https://en.wikipedia.org/wiki/Partial_application). + + @method fn + @public +*/ + +var fn = internalHelper(({ + positional +}) => { + let callbackRef = positional[0]; + if (DEBUG) assertCallbackIsFn(callbackRef); + return createComputeRef(() => { + return (...invocationArgs) => { + let [fn, ...args] = reifyPositional(positional); + if (DEBUG) assertCallbackIsFn(callbackRef); + + if (isInvokableRef(callbackRef)) { + let value = args.length > 0 ? args[0] : invocationArgs[0]; + return updateRef(callbackRef, value); + } else { + return fn.call(context, ...args, ...invocationArgs); + } + }; + }, null, 'fn'); +}); + +function assertCallbackIsFn(callbackRef) { + if (!(callbackRef && (isInvokableRef(callbackRef) || typeof valueForRef(callbackRef) === 'function'))) { + throw new Error(`You must pass a function as the \`fn\` helpers first argument, you passed ${callbackRef ? valueForRef(callbackRef) : callbackRef}. While rendering:\n\n${callbackRef === null || callbackRef === void 0 ? void 0 : callbackRef.debugLabel}`); + } +} + +let wrapHashProxy; + +if (DEBUG) { + wrapHashProxy = hash => { + return new Proxy(hash, { + set(target, key, value) { + deprecate(`You set the '${String(key)}' property on a {{hash}} object. Setting properties on objects generated by {{hash}} is deprecated. Please update to use an object created with a tracked property or getter, or with a custom helper.`, false, { + id: 'setting-on-hash' + }); + target[key] = value; + return true; + } + + }); + }; +} +/** + Use the `{{hash}}` helper to create a hash to pass as an option to your + components. This is specially useful for contextual components where you can + just yield a hash: + + ```handlebars + {{yield (hash + name='Sarah' + title=office + )}} + ``` + + Would result in an object such as: + + ```js + { name: 'Sarah', title: this.get('office') } + ``` + + Where the `title` is bound to updates of the `office` property. + + Note that the hash is an empty object with no prototype chain, therefore + common methods like `toString` are not available in the resulting hash. + If you need to use such a method, you can use the `call` or `apply` + approach: + + ```js + function toString(obj) { + return Object.prototype.toString.apply(obj); + } + ``` + + @method hash + @param {Object} options + @return {Object} Hash + @public + */ + + +var hash = internalHelper(({ + named +}) => { + let ref = createComputeRef(() => { + let hash = reifyNamed(named); + + if (DEBUG && HAS_NATIVE_PROXY) { + hash = wrapHashProxy(hash); + } + + return hash; + }, null, 'hash'); // Setup the children so that templates can bypass getting the value of + // the reference and treat children lazily + + let children = new Map(); + + for (let name in named) { + children.set(name, named[name]); + } + + ref.children = children; + return ref; +}); + +/** + Use the `{{array}}` helper to create an array to pass as an option to your + components. + + ```handlebars + + ``` + or + ```handlebars + {{my-component people=(array + 'Tom Dale' + 'Yehuda Katz' + this.myOtherPerson) + }} + ``` + + Would result in an object such as: + + ```js + ['Tom Dale', 'Yehuda Katz', this.get('myOtherPerson')] + ``` + + Where the 3rd item in the array is bound to updates of the `myOtherPerson` property. + + @method array + @param {Array} options + @return {Array} Array + @public + */ + +var array = internalHelper(({ + positional +}) => { + return createComputeRef(() => reifyPositional(positional), null, 'array'); +}); + +/** + Dynamically look up a property on an object. The second argument to `{{get}}` + should have a string value, although it can be bound. + + For example, these two usages are equivalent: + + ```app/components/developer-detail.js + import Component from '@glimmer/component'; + import { tracked } from '@glimmer/tracking'; + + export default class extends Component { + @tracked developer = { + name: "Sandi Metz", + language: "Ruby" + } + } + ``` + + ```handlebars + {{this.developer.name}} + {{get this.developer "name"}} + ``` + + If there were several facts about a person, the `{{get}}` helper can dynamically + pick one: + + ```app/templates/application.hbs + + ``` + + ```handlebars + {{get this.developer @factName}} + ``` + + For a more complex example, this template would allow the user to switch + between showing the user's height and weight with a click: + + ```app/components/developer-detail.js + import Component from '@glimmer/component'; + import { tracked } from '@glimmer/tracking'; + + export default class extends Component { + @tracked developer = { + name: "Sandi Metz", + language: "Ruby" + } + + @tracked currentFact = 'name' + + showFact = (fact) => { + this.currentFact = fact; + } + } + ``` + + ```app/components/developer-detail.js + {{get this.developer this.currentFact}} + + + + ``` + + The `{{get}}` helper can also respect mutable values itself. For example: + + ```app/components/developer-detail.js + + + + + ``` + + Would allow the user to swap what fact is being displayed, and also edit + that fact via a two-way mutable binding. + + @public + @method get + */ + +var get = internalHelper(({ + positional +}) => { + var _a, _b; + + let sourceRef = (_a = positional[0]) !== null && _a !== void 0 ? _a : UNDEFINED_REFERENCE; + let pathRef = (_b = positional[1]) !== null && _b !== void 0 ? _b : UNDEFINED_REFERENCE; + return createComputeRef(() => { + let source = valueForRef(sourceRef); + + if (isDict(source)) { + return getPath(source, String(valueForRef(pathRef))); + } + }, value => { + let source = valueForRef(sourceRef); + + if (isDict(source)) { + return setPath(source, String(valueForRef(pathRef)), value); + } + }, 'get'); +}); + +const isEmpty$2 = value => { + return value === null || value === undefined || typeof value.toString !== 'function'; +}; + +const normalizeTextValue = value => { + if (isEmpty$2(value)) { + return ''; + } + + return String(value); +}; +/** + Concatenates the given arguments into a string. + + Example: + + ```handlebars + {{some-component name=(concat firstName " " lastName)}} + + {{! would pass name=" " to the component}} + ``` + + or for angle bracket invocation, you actually don't need concat at all. + + ```handlebars + + ``` + + @public + @method concat +*/ + + +var concat = internalHelper(({ + positional +}) => { + return createComputeRef(() => reifyPositional(positional).map(normalizeTextValue).join(''), null, 'concat'); +}); + +const untouchableContext = buildUntouchableThis('`on` modifier'); +/* + Internet Explorer 11 does not support `once` and also does not support + passing `eventOptions`. In some situations it then throws a weird script + error, like: + + ``` + Could not complete the operation due to error 80020101 + ``` + + This flag determines, whether `{ once: true }` and thus also event options in + general are supported. +*/ + +const SUPPORTS_EVENT_OPTIONS = (() => { + try { + const div = document.createElement('div'); + let counter = 0; + div.addEventListener('click', () => counter++, { + once: true + }); + let event; + + if (typeof Event === 'function') { + event = new Event('click'); + } else { + event = document.createEvent('Event'); + event.initEvent('click', true, true); + } + + div.dispatchEvent(event); + div.dispatchEvent(event); + return counter === 1; + } catch (error) { + return false; + } +})(); + +class OnModifierState { + constructor(element, args) { + this.tag = createUpdatableTag(); + this.shouldUpdate = true; + this.element = element; + this.args = args; + } + + updateFromArgs() { + let { + args + } = this; + let { + once, + passive, + capture + } = reifyNamed(args.named); + + if (once !== this.once) { + this.once = once; + this.shouldUpdate = true; + } + + if (passive !== this.passive) { + this.passive = passive; + this.shouldUpdate = true; + } + + if (capture !== this.capture) { + this.capture = capture; + this.shouldUpdate = true; + } + + let options; + + if (once || passive || capture) { + options = this.options = { + once, + passive, + capture + }; + } else { + this.options = undefined; + } + + if (DEBUG && (args.positional[0] === undefined || typeof valueForRef(args.positional[0]) !== 'string')) { + throw new Error('You must pass a valid DOM event name as the first argument to the `on` modifier'); + } + + let eventName = valueForRef(args.positional[0]); + + if (eventName !== this.eventName) { + this.eventName = eventName; + this.shouldUpdate = true; + } + + let userProvidedCallbackReference = args.positional[1]; + + if (DEBUG) { + if (args.positional[1] === undefined) { + throw new Error(`You must pass a function as the second argument to the \`on\` modifier.`); + } + + let value = valueForRef(userProvidedCallbackReference); + + if (typeof value !== 'function') { + throw new Error(`You must pass a function as the second argument to the \`on\` modifier, you passed ${value === null ? 'null' : typeof value}. While rendering:\n\n${userProvidedCallbackReference.debugLabel}`); + } + } + + let userProvidedCallback = valueForRef(userProvidedCallbackReference); + + if (userProvidedCallback !== this.userProvidedCallback) { + this.userProvidedCallback = userProvidedCallback; + this.shouldUpdate = true; + } + + if (DEBUG && args.positional.length !== 2) { + throw new Error(`You can only pass two positional arguments (event name and callback) to the \`on\` modifier, but you provided ${args.positional.length}. Consider using the \`fn\` helper to provide additional arguments to the \`on\` callback.`); + } + + let needsCustomCallback = SUPPORTS_EVENT_OPTIONS === false && once || + /* needs manual once implementation */ + DEBUG && passive; + /* needs passive enforcement */ + + if (this.shouldUpdate) { + if (needsCustomCallback) { + let callback = this.callback = function (event) { + if (DEBUG && passive) { + event.preventDefault = () => { + throw new Error(`You marked this listener as 'passive', meaning that you must not call 'event.preventDefault()': \n\n${userProvidedCallback}`); + }; + } + + if (!SUPPORTS_EVENT_OPTIONS && once) { + removeEventListener(this, eventName, callback, options); + } + + return userProvidedCallback.call(untouchableContext, event); + }; + } else if (DEBUG) { + // prevent the callback from being bound to the element + this.callback = userProvidedCallback.bind(untouchableContext); + } else { + this.callback = userProvidedCallback; + } + } + } + +} +let adds = 0; +let removes = 0; + +function removeEventListener(element, eventName, callback, options) { + removes++; + + if (SUPPORTS_EVENT_OPTIONS) { + // when options are supported, use them across the board + element.removeEventListener(eventName, callback, options); + } else if (options !== undefined && options.capture) { + // used only in the following case: + // + // `{ once: true | false, passive: true | false, capture: true } + // + // `once` is handled via a custom callback that removes after first + // invocation so we only care about capture here as a boolean + element.removeEventListener(eventName, callback, true); + } else { + // used only in the following cases: + // + // * where there is no options + // * `{ once: true | false, passive: true | false, capture: false } + element.removeEventListener(eventName, callback); + } +} + +function addEventListener(element, eventName, callback, options) { + adds++; + + if (SUPPORTS_EVENT_OPTIONS) { + // when options are supported, use them across the board + element.addEventListener(eventName, callback, options); + } else if (options !== undefined && options.capture) { + // used only in the following case: + // + // `{ once: true | false, passive: true | false, capture: true } + // + // `once` is handled via a custom callback that removes after first + // invocation so we only care about capture here as a boolean + element.addEventListener(eventName, callback, true); + } else { + // used only in the following cases: + // + // * where there is no options + // * `{ once: true | false, passive: true | false, capture: false } + element.addEventListener(eventName, callback); + } +} +/** + The `{{on}}` modifier lets you easily add event listeners (it uses + [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) + internally). + + For example, if you'd like to run a function on your component when a ` + ``` + + ```app/components/like-post.js + import Component from '@glimmer/component'; + import { action } from '@ember/object'; + + export default class LikePostComponent extends Component { + saveLike = () => { + // someone likes your post! + // better send a request off to your server... + } + } + ``` + + ### Arguments + + `{{on}}` accepts two positional arguments, and a few named arguments. + + The positional arguments are: + + - `event` -- the name to use when calling `addEventListener` + - `callback` -- the function to be passed to `addEventListener` + + The named arguments are: + + - capture -- a `true` value indicates that events of this type will be dispatched + to the registered listener before being dispatched to any EventTarget beneath it + in the DOM tree. + - once -- indicates that the listener should be invoked at most once after being + added. If true, the listener would be automatically removed when invoked. + - passive -- if `true`, indicates that the function specified by listener will never + call preventDefault(). If a passive listener does call preventDefault(), the user + agent will do nothing other than generate a console warning. See + [Improving scrolling performance with passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners) + to learn more. + + The callback function passed to `{{on}}` will receive any arguments that are passed + to the event handler. Most commonly this would be the `event` itself. + + If you would like to pass additional arguments to the function you should use + the `{{fn}}` helper. + + For example, in our example case above if you'd like to pass in the post that + was being liked when the button is clicked you could do something like: + + ```app/components/like-post.hbs + + ``` + + In this case, the `saveLike` function will receive two arguments: the click event + and the value of `@post`. + + ### Function Context + + In the example above, we used an arrow function to ensure that `likePost` is + properly bound to the `items-list`, but let's explore what happens if we + left out the arrow function: + + ```app/components/like-post.js + import Component from '@glimmer/component'; + + export default class LikePostComponent extends Component { + saveLike() { + // ...snip... + } + } + ``` + + In this example, when the button is clicked `saveLike` will be invoked, + it will **not** have access to the component instance. In other + words, it will have no `this` context, so please make sure your functions + are bound (via an arrow function or other means) before passing into `on`! + + @method on + @public +*/ + + +class OnModifierManager { + constructor() { + this.SUPPORTS_EVENT_OPTIONS = SUPPORTS_EVENT_OPTIONS; + } + + getDebugName() { + return 'on'; + } + + get counters() { + return { + adds, + removes + }; + } + + create(_owner, element, _state, args) { + return new OnModifierState(element, args); + } + + getTag(state) { + if (state === null) { + return null; + } + + return state.tag; + } + + install(state) { + if (state === null) { + return; + } + + state.updateFromArgs(); + let { + element, + eventName, + callback, + options + } = state; + addEventListener(element, eventName, callback, options); + registerDestructor(state, () => removeEventListener(element, eventName, callback, options)); + state.shouldUpdate = false; + } + + update(state) { + if (state === null) { + return; + } // stash prior state for el.removeEventListener + + + let { + element, + eventName, + callback, + options + } = state; + state.updateFromArgs(); + + if (!state.shouldUpdate) { + return; + } // use prior state values for removal + + + removeEventListener(element, eventName, callback, options); // read updated values from the state object + + addEventListener(state.element, state.eventName, state.callback, state.options); + state.shouldUpdate = false; + } + + getDestroyable(state) { + return state; + } + +} + +var on = setInternalModifierManager(new OnModifierManager(), {}); + +export { clear, ConcreteBounds, CursorImpl, resetDebuggerCallback, setDebuggerCallback, curry, CurriedValue, TemplateOnlyComponentManager, TEMPLATE_ONLY_COMPONENT_MANAGER, TemplateOnlyComponentDefinition as TemplateOnlyComponent, templateOnlyComponent, helper$1 as DOMChanges, DOMChangesImpl as IDOMChanges, DOMTreeConstruction, isWhitespace, normalizeProperty, DynamicScopeImpl, PartialScopeImpl, runtimeContext, EnvironmentImpl, inTransaction, renderComponent, renderMain, renderSync, UpdatingVMImpl as UpdatingVM, VM as LowLevelVM, EMPTY_ARGS, EMPTY_NAMED, EMPTY_POSITIONAL, createCapturedArgs, reifyArgs, reifyNamed$1 as reifyNamed, reifyPositional$1 as reifyPositional, DynamicAttribute, dynamicAttribute, SimpleDynamicAttribute, clientBuilder, NewElementBuilder, UpdatableBlockImpl, RemoteLiveBlock, isSerializationFirstNode, RehydrateBuilder, rehydrationBuilder, SERIALIZATION_FIRST_NODE_STRING, invokeHelper, fn, hash, array, get, concat, on }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/util.js b/ember-vendored-pr-19806/dependencies/@glimmer/util.js new file mode 100644 index 0000000..3043b37 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/util.js @@ -0,0 +1,598 @@ +import { DEBUG } from '@glimmer/env'; + +const EMPTY_ARRAY = Object.freeze([]); +function emptyArray() { + return EMPTY_ARRAY; +} +const EMPTY_STRING_ARRAY = emptyArray(); +const EMPTY_NUMBER_ARRAY = emptyArray(); +/** + * This function returns `true` if the input array is the special empty array sentinel, + * which is sometimes used for optimizations. + */ + +function isEmptyArray(input) { + return input === EMPTY_ARRAY; +} + +// import Logger from './logger'; + +function debugAssert$$1(test, msg) { + // if (!alreadyWarned) { + // alreadyWarned = true; + // Logger.warn("Don't leave debug assertions on in public builds"); + // } + if (!test) { + throw new Error(msg || 'assertion failure'); + } +} +function deprecate$$1(desc) { + LOCAL_LOGGER.warn(`DEPRECATION: ${desc}`); +} + +function dict() { + return Object.create(null); +} +function isDict(u) { + return u !== null && u !== undefined; +} +function isObject(u) { + return typeof u === 'function' || typeof u === 'object' && u !== null; +} +class StackImpl { + constructor(values = []) { + this.current = null; + this.stack = values; + } + + get size() { + return this.stack.length; + } + + push(item) { + this.current = item; + this.stack.push(item); + } + + pop() { + let item = this.stack.pop(); + let len = this.stack.length; + this.current = len === 0 ? null : this.stack[len - 1]; + return item === undefined ? null : item; + } + + nth(from) { + let len = this.stack.length; + return len < from ? null : this.stack[len - from]; + } + + isEmpty() { + return this.stack.length === 0; + } + + toArray() { + return this.stack; + } + +} + +function clearElement(parent) { + let current = parent.firstChild; + + while (current) { + let next = current.nextSibling; + parent.removeChild(current); + current = next; + } +} + +const SERIALIZATION_FIRST_NODE_STRING = '%+b:0%'; +function isSerializationFirstNode(node) { + return node.nodeValue === SERIALIZATION_FIRST_NODE_STRING; +} + +var _a; + +const { + keys: objKeys +} = Object; + +function assignFn(obj) { + for (let i = 1; i < arguments.length; i++) { + let assignment = arguments[i]; + if (assignment === null || typeof assignment !== 'object') continue; + let keys = objKeys(assignment); + + for (let j = 0; j < keys.length; j++) { + let key = keys[j]; + obj[key] = assignment[key]; + } + } + + return obj; +} + +let assign = (_a = Object.assign) !== null && _a !== void 0 ? _a : assignFn; +function fillNulls(count) { + let arr = new Array(count); + + for (let i = 0; i < count; i++) { + arr[i] = null; + } + + return arr; +} +function values(obj) { + const vals = []; + + for (const key in obj) { + vals.push(obj[key]); + } + + return vals; +} + +/** + Strongly hint runtimes to intern the provided string. + + When do I need to use this function? + + For the most part, never. Pre-mature optimization is bad, and often the + runtime does exactly what you need it to, and more often the trade-off isn't + worth it. + + Why? + + Runtimes store strings in at least 2 different representations: + Ropes and Symbols (interned strings). The Rope provides a memory efficient + data-structure for strings created from concatenation or some other string + manipulation like splitting. + + Unfortunately checking equality of different ropes can be quite costly as + runtimes must resort to clever string comparison algorithms. These + algorithms typically cost in proportion to the length of the string. + Luckily, this is where the Symbols (interned strings) shine. As Symbols are + unique by their string content, equality checks can be done by pointer + comparison. + + How do I know if my string is a rope or symbol? + + Typically (warning general sweeping statement, but truthy in runtimes at + present) static strings created as part of the JS source are interned. + Strings often used for comparisons can be interned at runtime if some + criteria are met. One of these criteria can be the size of the entire rope. + For example, in chrome 38 a rope longer then 12 characters will not + intern, nor will segments of that rope. + + Some numbers: http://jsperf.com/eval-vs-keys/8 + + Known Trick™ + + @private + @return {String} interned version of the provided string +*/ +function intern(str) { + let obj = {}; + obj[str] = 1; + + for (let key in obj) { + if (key === str) { + return key; + } + } + + return str; +} + +const HAS_NATIVE_PROXY = typeof Proxy === 'function'; +const HAS_NATIVE_SYMBOL = function () { + if (typeof Symbol !== 'function') { + return false; + } // eslint-disable-next-line symbol-description + + + return typeof Symbol() === 'symbol'; +}(); +function keys(obj) { + return Object.keys(obj); +} +function unwrap(val) { + if (val === null || val === undefined) throw new Error(`Expected value to be present`); + return val; +} +function expect(val, message) { + if (val === null || val === undefined) throw new Error(message); + return val; +} +function unreachable(message = 'unreachable') { + return new Error(message); +} +function exhausted(value) { + throw new Error(`Exhausted ${value}`); +} +const tuple = (...args) => args; +function enumerableSymbol(key) { + return intern(`__${key}${Math.floor(Math.random() * Date.now())}__`); +} +const symbol = HAS_NATIVE_SYMBOL ? Symbol : enumerableSymbol; + +function strip(strings, ...args) { + let out = ''; + + for (let i = 0; i < strings.length; i++) { + let string = strings[i]; + let dynamic = args[i] !== undefined ? String(args[i]) : ''; + out += `${string}${dynamic}`; + } + + let lines = out.split('\n'); + + while (lines.length && lines[0].match(/^\s*$/)) { + lines.shift(); + } + + while (lines.length && lines[lines.length - 1].match(/^\s*$/)) { + lines.pop(); + } + + let min = Infinity; + + for (let line of lines) { + let leading = line.match(/^\s*/)[0].length; + min = Math.min(min, leading); + } + + let stripped = []; + + for (let line of lines) { + stripped.push(line.slice(min)); + } + + return stripped.join('\n'); +} + +function isHandle(value) { + return value >= 0; +} +function isNonPrimitiveHandle(value) { + return value > 3 + /* ENCODED_UNDEFINED_HANDLE */ + ; +} +function constants(...values) { + return [false, true, null, undefined, ...values]; +} +function isSmallInt(value) { + return value % 1 === 0 && value <= 536870911 + /* MAX_INT */ + && value >= -536870912 + /* MIN_INT */ + ; +} +function encodeNegative(num) { + + return num & -536870913 + /* SIGN_BIT */ + ; +} +function decodeNegative(num) { + + return num | ~-536870913 + /* SIGN_BIT */ + ; +} +function encodePositive(num) { + + return ~num; +} +function decodePositive(num) { + + return ~num; +} +function encodeHandle(num) { + + return num; +} +function decodeHandle(num) { + + return num; +} +function encodeImmediate(num) { + num |= 0; + return num < 0 ? encodeNegative(num) : encodePositive(num); +} +function decodeImmediate(num) { + num |= 0; + return num > -536870913 + /* SIGN_BIT */ + ? decodePositive(num) : decodeNegative(num); +} // Warm +[1, -1].forEach(x => decodeImmediate(encodeImmediate(x))); + +function unwrapHandle(handle) { + if (typeof handle === 'number') { + return handle; + } else { + let error = handle.errors[0]; + throw new Error(`Compile Error: ${error.problem} @ ${error.span.start}..${error.span.end}`); + } +} +function unwrapTemplate(template) { + if (template.result === 'error') { + throw new Error(`Compile Error: ${template.problem} @ ${template.span.start}..${template.span.end}`); + } + + return template; +} +function extractHandle(handle) { + if (typeof handle === 'number') { + return handle; + } else { + return handle.handle; + } +} +function isOkHandle(handle) { + return typeof handle === 'number'; +} +function isErrHandle(handle) { + return typeof handle === 'number'; +} + +var weakSet = typeof WeakSet === 'function' ? WeakSet : class WeakSetPolyFill { + constructor() { + this._map = new WeakMap(); + } + + add(val) { + this._map.set(val, true); + + return this; + } + + delete(val) { + return this._map.delete(val); + } + + has(val) { + return this._map.has(val); + } + +}; + +function castToSimple(node) { + if (isDocument(node)) { + return node; + } else if (isElement(node)) { + return node; + } else { + return node; + } +} +function castToBrowser(node, sugaryCheck) { + if (node === null || node === undefined) { + return null; + } + + if (typeof document === undefined) { + throw new Error('Attempted to cast to a browser node in a non-browser context'); + } + + if (isDocument(node)) { + return node; + } + + if (node.ownerDocument !== document) { + throw new Error('Attempted to cast to a browser node with a node that was not created from this document'); + } + + return checkNode(node, sugaryCheck); +} + +function checkError(from, check) { + return new Error(`cannot cast a ${from} into ${check}`); +} + +function isDocument(node) { + return node.nodeType === 9 + /* DOCUMENT_NODE */ + ; +} + +function isElement(node) { + return node.nodeType === 1 + /* ELEMENT_NODE */ + ; +} + +function checkNode(node, check) { + let isMatch = false; + + if (node !== null) { + if (typeof check === 'string') { + isMatch = stringCheckNode(node, check); + } else if (Array.isArray(check)) { + isMatch = check.some(c => stringCheckNode(node, c)); + } else { + throw unreachable(); + } + } + + if (isMatch) { + return node; + } else { + throw checkError(`SimpleElement(${node})`, check); + } +} + +function stringCheckNode(node, check) { + switch (check) { + case 'NODE': + return true; + + case 'HTML': + return node instanceof HTMLElement; + + case 'SVG': + return node instanceof SVGElement; + + case 'ELEMENT': + return node instanceof Element; + + default: + if (check.toUpperCase() === check) { + throw new Error(`BUG: this code is missing handling for a generic node type`); + } + + return node instanceof Element && node.tagName.toLowerCase() === check; + } +} + +function isPresent(list) { + return list.length > 0; +} +function ifPresent(list, ifPresent, otherwise) { + if (isPresent(list)) { + return ifPresent(list); + } else { + return otherwise(); + } +} +function toPresentOption(list) { + if (isPresent(list)) { + return list; + } else { + return null; + } +} +function assertPresent(list, message = `unexpected empty list`) { + if (!isPresent(list)) { + throw new Error(message); + } +} +function mapPresent(list, callback) { + if (list === null) { + return null; + } + + let out = []; + + for (let item of list) { + out.push(callback(item)); + } + + return out; +} + +function buildUntouchableThis(source) { + let context = null; + + if (DEBUG && HAS_NATIVE_PROXY) { + let assertOnProperty = property => { + throw new Error(`You accessed \`this.${String(property)}\` from a function passed to the ${source}, but the function itself was not bound to a valid \`this\` context. Consider updating to use a bound function (for instance, use an arrow function, \`() => {}\`).`); + }; + + context = new Proxy({}, { + get(_target, property) { + assertOnProperty(property); + }, + + set(_target, property) { + assertOnProperty(property); + return false; + }, + + has(_target, property) { + assertOnProperty(property); + return false; + } + + }); + } + + return context; +} + +let debugToString; + +if (DEBUG) { + let getFunctionName = fn => { + let functionName = fn.name; + + if (functionName === undefined) { + let match = Function.prototype.toString.call(fn).match(/function (\w+)\s*\(/); + functionName = match && match[1] || ''; + } + + return functionName.replace(/^bound /, ''); + }; + + let getObjectName = obj => { + let name; + let className; + + if (obj.constructor && typeof obj.constructor === 'function') { + className = getFunctionName(obj.constructor); + } + + if ('toString' in obj && obj.toString !== Object.prototype.toString && obj.toString !== Function.prototype.toString) { + name = obj.toString(); + } // If the class has a decent looking name, and the `toString` is one of the + // default Ember toStrings, replace the constructor portion of the toString + // with the class name. We check the length of the class name to prevent doing + // this when the value is minified. + + + if (name && name.match(/<.*:ember\d+>/) && className && className[0] !== '_' && className.length > 2 && className !== 'Class') { + return name.replace(/<.*:/, `<${className}:`); + } + + return name || className; + }; + + let getPrimitiveName = value => { + return String(value); + }; + + debugToString = value => { + if (typeof value === 'function') { + return getFunctionName(value) || `(unknown function)`; + } else if (typeof value === 'object' && value !== null) { + return getObjectName(value) || `(unknown object)`; + } else { + return getPrimitiveName(value); + } + }; +} + +var debugToString$1 = debugToString; + +let beginTestSteps; +let endTestSteps; +let verifySteps; +let logStep; + +/** + * This constant exists to make it easier to differentiate normal logs from + * errant console.logs. LOCAL_LOGGER should only be used inside a + * LOCAL_SHOULD_LOG check. + * + * It does not alleviate the need to check LOCAL_SHOULD_LOG, which is used + * for stripping. + */ + +const LOCAL_LOGGER = console; +/** + * This constant exists to make it easier to differentiate normal logs from + * errant console.logs. LOGGER can be used outside of LOCAL_SHOULD_LOG checks, + * and is meant to be used in the rare situation where a console.* call is + * actually appropriate. + */ + +const LOGGER = console; +function assertNever(value, desc = 'unexpected unreachable branch') { + LOGGER.log('unreachable', value); + LOGGER.log(`${desc} :: ${JSON.stringify(value)} (${value})`); + throw new Error(`code reached unreachable`); +} + +export { LOCAL_LOGGER, LOGGER, assertNever, debugAssert$$1 as assert, deprecate$$1 as deprecate, dict, isDict, isObject, StackImpl as Stack, isSerializationFirstNode, SERIALIZATION_FIRST_NODE_STRING, assign, fillNulls, values, weakSet as _WeakSet, castToSimple, castToBrowser, checkNode, intern, buildUntouchableThis, debugToString$1 as debugToString, beginTestSteps, endTestSteps, logStep, verifySteps, EMPTY_ARRAY, emptyArray, EMPTY_STRING_ARRAY, EMPTY_NUMBER_ARRAY, isEmptyArray, clearElement, HAS_NATIVE_PROXY, HAS_NATIVE_SYMBOL, keys, unwrap, expect, unreachable, exhausted, tuple, enumerableSymbol, symbol, strip, isHandle, isNonPrimitiveHandle, constants, isSmallInt, encodeNegative, decodeNegative, encodePositive, decodePositive, encodeHandle, decodeHandle, encodeImmediate, decodeImmediate, unwrapHandle, unwrapTemplate, extractHandle, isOkHandle, isErrHandle, isPresent, ifPresent, toPresentOption, assertPresent, mapPresent }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/validator.js b/ember-vendored-pr-19806/dependencies/@glimmer/validator.js new file mode 100644 index 0000000..132f59f --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/validator.js @@ -0,0 +1,768 @@ +import { DEBUG } from '@glimmer/env'; +import { deprecate, assert, scheduleRevalidate } from '@glimmer/global-context'; + +// eslint-disable-next-line @typescript-eslint/ban-types +function indexable(input) { + return input; +} // This is a duplicate utility from @glimmer/util because `@glimmer/validator` +// should not depend on any other @glimmer packages, in order to avoid pulling +// in types and prevent regressions in `@glimmer/tracking` (which has public types). + +const symbol = typeof Symbol !== 'undefined' ? Symbol : // eslint-disable-next-line @typescript-eslint/no-explicit-any +key => `__${key}${Math.floor(Math.random() * Date.now())}__`; // eslint-disable-next-line @typescript-eslint/no-explicit-any + +const symbolFor = typeof Symbol !== 'undefined' ? Symbol.for : key => `__GLIMMER_VALIDATOR_SYMBOL_FOR_${key}`; +function getGlobal() { + // eslint-disable-next-line node/no-unsupported-features/es-builtins + if (typeof globalThis !== 'undefined') return indexable(globalThis); + if (typeof self !== 'undefined') return indexable(self); + if (typeof window !== 'undefined') return indexable(window); + if (typeof global !== 'undefined') return indexable(global); + throw new Error('unable to locate global object'); +} +function unwrap(val) { + if (val === null || val === undefined) throw new Error(`Expected value to be present`); + return val; +} + +let beginTrackingTransaction; +let endTrackingTransaction; +let runInTrackingTransaction; +let deprecateMutationsInTrackingTransaction; +let resetTrackingTransaction; +let setTrackingTransactionEnv; +let assertTagNotConsumed; +let markTagAsConsumed; +let logTrackingStack; + +if (DEBUG) { + let CONSUMED_TAGS = null; + let TRANSACTION_STACK = []; ///////// + + let TRANSACTION_ENV = { + debugMessage(obj, keyName) { + let objName; + + if (typeof obj === 'function') { + objName = obj.name; + } else if (typeof obj === 'object' && obj !== null) { + let className = obj.constructor && obj.constructor.name || '(unknown class)'; + objName = `(an instance of ${className})`; + } else if (obj === undefined) { + objName = '(an unknown tag)'; + } else { + objName = String(obj); + } + + let dirtyString = keyName ? `\`${keyName}\` on \`${objName}\`` : `\`${objName}\``; + return `You attempted to update ${dirtyString}, but it had already been used previously in the same computation. Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.`; + } + + }; + + setTrackingTransactionEnv = env => Object.assign(TRANSACTION_ENV, env); + + beginTrackingTransaction = (_debugLabel, deprecate$$1 = false) => { + CONSUMED_TAGS = CONSUMED_TAGS || new WeakMap(); + let debugLabel = _debugLabel || undefined; + let parent = TRANSACTION_STACK[TRANSACTION_STACK.length - 1] || null; + TRANSACTION_STACK.push({ + parent, + debugLabel, + deprecate: deprecate$$1 + }); + }; + + endTrackingTransaction = () => { + if (TRANSACTION_STACK.length === 0) { + throw new Error('attempted to close a tracking transaction, but one was not open'); + } + + TRANSACTION_STACK.pop(); + + if (TRANSACTION_STACK.length === 0) { + CONSUMED_TAGS = null; + } + }; + + resetTrackingTransaction = () => { + let stack = ''; + + if (TRANSACTION_STACK.length > 0) { + stack = logTrackingStack(TRANSACTION_STACK[TRANSACTION_STACK.length - 1]); + } + + TRANSACTION_STACK = []; + CONSUMED_TAGS = null; + return stack; + }; + /** + * Creates a global autotracking transaction. This will prevent any backflow + * in any `track` calls within the transaction, even if they are not + * externally consumed. + * + * `runInAutotrackingTransaction` can be called within itself, and it will add + * onto the existing transaction if one exists. + * + * TODO: Only throw an error if the `track` is consumed. + */ + + + runInTrackingTransaction = (fn, debugLabel) => { + beginTrackingTransaction(debugLabel); + let didError = true; + + try { + let value = fn(); + didError = false; + return value; + } finally { + if (didError !== true) { + endTrackingTransaction(); + } + } + }; + /** + * Switches to deprecating within an autotracking transaction, if one exists. + * If `runInAutotrackingTransaction` is called within the callback of this + * method, it switches back to throwing an error, allowing zebra-striping of + * the types of errors that are thrown. + * + * Does not start an autotracking transaction. + * + * NOTE: For Ember usage only, in general you should assert that these + * invariants are true. + */ + + + deprecateMutationsInTrackingTransaction = (fn, debugLabel) => { + beginTrackingTransaction(debugLabel, true); + + try { + fn(); + } finally { + endTrackingTransaction(); + } + }; + + let nthIndex = (str, pattern, n, startingPos = -1) => { + let i = startingPos; + + while (n-- > 0 && i++ < str.length) { + i = str.indexOf(pattern, i); + if (i < 0) break; + } + + return i; + }; + + let makeTrackingErrorMessage = (transaction, obj, keyName) => { + let message = [TRANSACTION_ENV.debugMessage(obj, keyName && String(keyName))]; + message.push(`\`${String(keyName)}\` was first used:`); + message.push(logTrackingStack(transaction)); + message.push(`Stack trace for the update:`); + return message.join('\n\n'); + }; + + logTrackingStack = transaction => { + let trackingStack = []; + let current = transaction || TRANSACTION_STACK[TRANSACTION_STACK.length - 1]; + if (current === undefined) return ''; + + while (current) { + if (current.debugLabel) { + trackingStack.unshift(current.debugLabel); + } + + current = current.parent; + } // TODO: Use String.prototype.repeat here once we can drop support for IE11 + + + return trackingStack.map((label, index) => Array(2 * index + 1).join(' ') + label).join('\n'); + }; + + markTagAsConsumed = _tag => { + if (!CONSUMED_TAGS || CONSUMED_TAGS.has(_tag)) return; + CONSUMED_TAGS.set(_tag, TRANSACTION_STACK[TRANSACTION_STACK.length - 1]); // We need to mark the tag and all of its subtags as consumed, so we need to + // cast it and access its internals. In the future this shouldn't be necessary, + // this is only for computed properties. + + let tag = _tag; + + if (tag.subtag) { + markTagAsConsumed(tag.subtag); + } + + if (tag.subtags) { + tag.subtags.forEach(tag => markTagAsConsumed(tag)); + } + }; + + assertTagNotConsumed = (tag, obj, keyName) => { + if (CONSUMED_TAGS === null) return; + let transaction = CONSUMED_TAGS.get(tag); + if (!transaction) return; + let currentTransaction = TRANSACTION_STACK[TRANSACTION_STACK.length - 1]; + + if (currentTransaction.deprecate) { + deprecate(makeTrackingErrorMessage(transaction, obj, keyName), false, { + id: 'autotracking.mutation-after-consumption' + }); + } else { + // This hack makes the assertion message nicer, we can cut off the first + // few lines of the stack trace and let users know where the actual error + // occurred. + try { + assert(false, makeTrackingErrorMessage(transaction, obj, keyName)); + } catch (e) { + if (e.stack) { + let updateStackBegin = e.stack.indexOf('Stack trace for the update:'); + + if (updateStackBegin !== -1) { + let start = nthIndex(e.stack, '\n', 1, updateStackBegin); + let end = nthIndex(e.stack, '\n', 4, updateStackBegin); + e.stack = e.stack.substr(0, start) + e.stack.substr(end); + } + } + + throw e; + } + } + }; +} + +const CONSTANT = 0; +const INITIAL = 1; +const VOLATILE = NaN; +let $REVISION = INITIAL; +function bump() { + $REVISION++; +} ////////// + +const COMPUTE = symbol('TAG_COMPUTE'); ////////// + +/** + * `value` receives a tag and returns an opaque Revision based on that tag. This + * snapshot can then later be passed to `validate` with the same tag to + * determine if the tag has changed at all since the time that `value` was + * called. + * + * @param tag + */ + +function valueForTag(tag) { + return tag[COMPUTE](); +} +/** + * `validate` receives a tag and a snapshot from a previous call to `value` with + * the same tag, and determines if the tag is still valid compared to the + * snapshot. If the tag's state has changed at all since then, `validate` will + * return false, otherwise it will return true. This is used to determine if a + * calculation related to the tags should be rerun. + * + * @param tag + * @param snapshot + */ + +function validateTag(tag, snapshot) { + return snapshot >= tag[COMPUTE](); +} +const TYPE = symbol('TAG_TYPE'); // this is basically a const +// eslint-disable-next-line @typescript-eslint/naming-convention + +let ALLOW_CYCLES; + +if (DEBUG) { + ALLOW_CYCLES = new WeakMap(); +} + +function allowsCycles(tag) { + if (ALLOW_CYCLES === undefined) { + return true; + } else { + return ALLOW_CYCLES.has(tag); + } +} + +class MonomorphicTagImpl { + constructor(type) { + this.revision = INITIAL; + this.lastChecked = INITIAL; + this.lastValue = INITIAL; + this.isUpdating = false; + this.subtag = null; + this.subtagBufferCache = null; + this[TYPE] = type; + } + + static combine(tags) { + switch (tags.length) { + case 0: + return CONSTANT_TAG; + + case 1: + return tags[0]; + + default: + let tag = new MonomorphicTagImpl(2 + /* Combinator */ + ); + tag.subtag = tags; + return tag; + } + } + + [COMPUTE]() { + let { + lastChecked + } = this; + + if (this.isUpdating === true) { + if (DEBUG && !allowsCycles(this)) { + throw new Error('Cycles in tags are not allowed'); + } + + this.lastChecked = ++$REVISION; + } else if (lastChecked !== $REVISION) { + this.isUpdating = true; + this.lastChecked = $REVISION; + + try { + let { + subtag, + revision + } = this; + + if (subtag !== null) { + if (Array.isArray(subtag)) { + for (let i = 0; i < subtag.length; i++) { + let value = subtag[i][COMPUTE](); + revision = Math.max(value, revision); + } + } else { + let subtagValue = subtag[COMPUTE](); + + if (subtagValue === this.subtagBufferCache) { + revision = Math.max(revision, this.lastValue); + } else { + // Clear the temporary buffer cache + this.subtagBufferCache = null; + revision = Math.max(revision, subtagValue); + } + } + } + + this.lastValue = revision; + } finally { + this.isUpdating = false; + } + } + + return this.lastValue; + } + + static updateTag(_tag, _subtag) { + if (DEBUG && _tag[TYPE] !== 1 + /* Updatable */ + ) { + throw new Error('Attempted to update a tag that was not updatable'); + } // TODO: TS 3.7 should allow us to do this via assertion + + + let tag = _tag; + let subtag = _subtag; + + if (subtag === CONSTANT_TAG) { + tag.subtag = null; + } else { + // There are two different possibilities when updating a subtag: + // + // 1. subtag[COMPUTE]() <= tag[COMPUTE](); + // 2. subtag[COMPUTE]() > tag[COMPUTE](); + // + // The first possibility is completely fine within our caching model, but + // the second possibility presents a problem. If the parent tag has + // already been read, then it's value is cached and will not update to + // reflect the subtag's greater value. Next time the cache is busted, the + // subtag's value _will_ be read, and it's value will be _greater_ than + // the saved snapshot of the parent, causing the resulting calculation to + // be rerun erroneously. + // + // In order to prevent this, when we first update to a new subtag we store + // its computed value, and then check against that computed value on + // subsequent updates. If its value hasn't changed, then we return the + // parent's previous value. Once the subtag changes for the first time, + // we clear the cache and everything is finally in sync with the parent. + tag.subtagBufferCache = subtag[COMPUTE](); + tag.subtag = subtag; + } + } + + static dirtyTag(tag, disableConsumptionAssertion) { + if (DEBUG && !(tag[TYPE] === 1 + /* Updatable */ + || tag[TYPE] === 0 + /* Dirtyable */ + )) { + throw new Error('Attempted to dirty a tag that was not dirtyable'); + } + + if (DEBUG && disableConsumptionAssertion !== true) { + // Usually by this point, we've already asserted with better error information, + // but this is our last line of defense. + unwrap(assertTagNotConsumed)(tag); + } + + tag.revision = ++$REVISION; + scheduleRevalidate(); + } + +} + +const DIRTY_TAG = MonomorphicTagImpl.dirtyTag; +const UPDATE_TAG = MonomorphicTagImpl.updateTag; ////////// + +function createTag() { + return new MonomorphicTagImpl(0 + /* Dirtyable */ + ); +} +function createUpdatableTag() { + return new MonomorphicTagImpl(1 + /* Updatable */ + ); +} ////////// + +const CONSTANT_TAG = new MonomorphicTagImpl(3 +/* Constant */ +); +function isConstTag(tag) { + return tag === CONSTANT_TAG; +} ////////// + +class VolatileTag { + [COMPUTE]() { + return VOLATILE; + } + +} +const VOLATILE_TAG = new VolatileTag(); ////////// + +class CurrentTag { + [COMPUTE]() { + return $REVISION; + } + +} +const CURRENT_TAG = new CurrentTag(); ////////// + +const combine = MonomorphicTagImpl.combine; // Warm + +let tag1 = createUpdatableTag(); +let tag2 = createUpdatableTag(); +let tag3 = createUpdatableTag(); +valueForTag(tag1); +DIRTY_TAG(tag1); +valueForTag(tag1); +UPDATE_TAG(tag1, combine([tag2, tag3])); +valueForTag(tag1); +DIRTY_TAG(tag2); +valueForTag(tag1); +DIRTY_TAG(tag3); +valueForTag(tag1); +UPDATE_TAG(tag1, tag3); +valueForTag(tag1); +DIRTY_TAG(tag3); +valueForTag(tag1); + +function isObjectLike(u) { + return typeof u === 'object' && u !== null || typeof u === 'function'; +} + +const TRACKED_TAGS = new WeakMap(); +function dirtyTagFor(obj, key, meta) { + if (DEBUG && !isObjectLike(obj)) { + throw new Error(`BUG: Can't update a tag for a primitive`); + } + + let tags = meta === undefined ? TRACKED_TAGS.get(obj) : meta; // No tags have been setup for this object yet, return + + if (tags === undefined) return; // Dirty the tag for the specific property if it exists + + let propertyTag = tags.get(key); + + if (propertyTag !== undefined) { + if (DEBUG) { + unwrap(assertTagNotConsumed)(propertyTag, obj, key); + } + + DIRTY_TAG(propertyTag, true); + } +} +function tagMetaFor(obj) { + let tags = TRACKED_TAGS.get(obj); + + if (tags === undefined) { + tags = new Map(); + TRACKED_TAGS.set(obj, tags); + } + + return tags; +} +function tagFor(obj, key, meta) { + let tags = meta === undefined ? tagMetaFor(obj) : meta; + let tag = tags.get(key); + + if (tag === undefined) { + tag = createUpdatableTag(); + tags.set(key, tag); + } + + return tag; +} + +/** + * An object that that tracks @tracked properties that were consumed. + */ + +class Tracker { + constructor() { + this.tags = new Set(); + this.last = null; + } + + add(tag) { + if (tag === CONSTANT_TAG) return; + this.tags.add(tag); + + if (DEBUG) { + unwrap(markTagAsConsumed)(tag); + } + + this.last = tag; + } + + combine() { + let { + tags + } = this; + + if (tags.size === 0) { + return CONSTANT_TAG; + } else if (tags.size === 1) { + return this.last; + } else { + let tagsArr = []; + tags.forEach(tag => tagsArr.push(tag)); + return combine(tagsArr); + } + } + +} +/** + * Whenever a tracked computed property is entered, the current tracker is + * saved off and a new tracker is replaced. + * + * Any tracked properties consumed are added to the current tracker. + * + * When a tracked computed property is exited, the tracker's tags are + * combined and added to the parent tracker. + * + * The consequence is that each tracked computed property has a tag + * that corresponds to the tracked properties consumed inside of + * itself, including child tracked computed properties. + */ + + +let CURRENT_TRACKER = null; +const OPEN_TRACK_FRAMES = []; +function beginTrackFrame(debuggingContext) { + OPEN_TRACK_FRAMES.push(CURRENT_TRACKER); + CURRENT_TRACKER = new Tracker(); + + if (DEBUG) { + unwrap(beginTrackingTransaction)(debuggingContext); + } +} +function endTrackFrame() { + let current = CURRENT_TRACKER; + + if (DEBUG) { + if (OPEN_TRACK_FRAMES.length === 0) { + throw new Error('attempted to close a tracking frame, but one was not open'); + } + + unwrap(endTrackingTransaction)(); + } + + CURRENT_TRACKER = OPEN_TRACK_FRAMES.pop() || null; + return unwrap(current).combine(); +} +function beginUntrackFrame() { + OPEN_TRACK_FRAMES.push(CURRENT_TRACKER); + CURRENT_TRACKER = null; +} +function endUntrackFrame() { + if (DEBUG && OPEN_TRACK_FRAMES.length === 0) { + throw new Error('attempted to close a tracking frame, but one was not open'); + } + + CURRENT_TRACKER = OPEN_TRACK_FRAMES.pop() || null; +} // This function is only for handling errors and resetting to a valid state + +function resetTracking() { + while (OPEN_TRACK_FRAMES.length > 0) { + OPEN_TRACK_FRAMES.pop(); + } + + CURRENT_TRACKER = null; + + if (DEBUG) { + return unwrap(resetTrackingTransaction)(); + } +} +function isTracking() { + return CURRENT_TRACKER !== null; +} +function consumeTag(tag) { + if (CURRENT_TRACKER !== null) { + CURRENT_TRACKER.add(tag); + } +} ////////// +const FN = symbol('FN'); +const LAST_VALUE = symbol('LAST_VALUE'); +const TAG = symbol('TAG'); +const SNAPSHOT = symbol('SNAPSHOT'); +const DEBUG_LABEL = symbol('DEBUG_LABEL'); +function createCache(fn, debuggingLabel) { + if (DEBUG && !(typeof fn === 'function')) { + throw new Error(`createCache() must be passed a function as its first parameter. Called with: ${String(fn)}`); + } + + let cache = { + [FN]: fn, + [LAST_VALUE]: undefined, + [TAG]: undefined, + [SNAPSHOT]: -1 + }; + + if (DEBUG) { + cache[DEBUG_LABEL] = debuggingLabel; + } + + return cache; +} +function getValue(cache) { + assertCache(cache, 'getValue'); + let fn = cache[FN]; + let tag = cache[TAG]; + let snapshot = cache[SNAPSHOT]; + + if (tag === undefined || !validateTag(tag, snapshot)) { + beginTrackFrame(); + + try { + cache[LAST_VALUE] = fn(); + } finally { + tag = endTrackFrame(); + cache[TAG] = tag; + cache[SNAPSHOT] = valueForTag(tag); + consumeTag(tag); + } + } else { + consumeTag(tag); + } + + return cache[LAST_VALUE]; +} +function isConst(cache) { + assertCache(cache, 'isConst'); + let tag = cache[TAG]; + assertTag(tag, cache); + return isConstTag(tag); +} + +function assertCache(value, fnName) { + if (DEBUG && !(typeof value === 'object' && value !== null && FN in value)) { + throw new Error(`${fnName}() can only be used on an instance of a cache created with createCache(). Called with: ${String(value)}`); + } +} // replace this with `expect` when we can + + +function assertTag(tag, cache) { + if (DEBUG && tag === undefined) { + throw new Error(`isConst() can only be used on a cache once getValue() has been called at least once. Called with cache function:\n\n${String(cache[FN])}`); + } +} ////////// +// Legacy tracking APIs +// track() shouldn't be necessary at all in the VM once the autotracking +// refactors are merged, and we should generally be moving away from it. It may +// be necessary in Ember for a while longer, but I think we'll be able to drop +// it in favor of cache sooner rather than later. + + +function track(callback, debugLabel) { + beginTrackFrame(debugLabel); + let tag; + + try { + callback(); + } finally { + tag = endTrackFrame(); + } + + return tag; +} // untrack() is currently mainly used to handle places that were previously not +// tracked, and that tracking now would cause backtracking rerender assertions. +// I think once we move everyone forward onto modern APIs, we'll probably be +// able to remove it, but I'm not sure yet. + +function untrack(callback) { + beginUntrackFrame(); + + try { + return callback(); + } finally { + endUntrackFrame(); + } +} + +function trackedData(key, initializer) { + let values = new WeakMap(); + let hasInitializer = typeof initializer === 'function'; + + function getter(self) { + consumeTag(tagFor(self, key)); + let value; // If the field has never been initialized, we should initialize it + + if (hasInitializer && !values.has(self)) { + value = initializer.call(self); + values.set(self, value); + } else { + value = values.get(self); + } + + return value; + } + + function setter(self, value) { + dirtyTagFor(self, key); + values.set(self, value); + } + + return { + getter, + setter + }; +} + +const GLIMMER_VALIDATOR_REGISTRATION = symbolFor('GLIMMER_VALIDATOR_REGISTRATION'); +const globalObj = getGlobal(); + +if (globalObj[GLIMMER_VALIDATOR_REGISTRATION] === true) { + throw new Error('The `@glimmer/validator` library has been included twice in this application. It could be different versions of the package, or the same version included twice by mistake. `@glimmer/validator` depends on having a single copy of the package in use at any time in an application, even if they are the same version. You must dedupe your build to remove the duplicate packages in order to prevent this error.'); +} + +globalObj[GLIMMER_VALIDATOR_REGISTRATION] = true; + +export { ALLOW_CYCLES, bump, combine, COMPUTE, CONSTANT_TAG, CONSTANT, createTag, createUpdatableTag, CurrentTag, CURRENT_TAG, DIRTY_TAG as dirtyTag, INITIAL, isConstTag, UPDATE_TAG as updateTag, validateTag, valueForTag, VolatileTag, VOLATILE_TAG, VOLATILE, dirtyTagFor, tagFor, tagMetaFor, beginTrackFrame, endTrackFrame, beginUntrackFrame, endUntrackFrame, resetTracking, consumeTag, isTracking, track, untrack, createCache, isConst, getValue, trackedData, logTrackingStack, setTrackingTransactionEnv, runInTrackingTransaction, beginTrackingTransaction, endTrackingTransaction, deprecateMutationsInTrackingTransaction }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/vm.js b/ember-vendored-pr-19806/dependencies/@glimmer/vm.js new file mode 100644 index 0000000..41a6b35 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/vm.js @@ -0,0 +1,48 @@ +/* This file is generated by build/debug.js */ +function isMachineOp(value) { + return value >= 0 && value <= 15; +} +function isOp(value) { + return value >= 16; +} + +/** + * Registers + * + * For the most part, these follows MIPS naming conventions, however the + * register numbers are different. + */ +// $0 or $pc (program counter): pointer into `program` for the next insturction; -1 means exit +const $pc = 0; // $1 or $ra (return address): pointer into `program` for the return + +const $ra = 1; // $2 or $fp (frame pointer): pointer into the `evalStack` for the base of the stack + +const $fp = 2; // $3 or $sp (stack pointer): pointer into the `evalStack` for the top of the stack + +const $sp = 3; // $4-$5 or $s0-$s1 (saved): callee saved general-purpose registers + +const $s0 = 4; +const $s1 = 5; // $6-$7 or $t0-$t1 (temporaries): caller saved general-purpose registers + +const $t0 = 6; +const $t1 = 7; // $8 or $v0 (return value) + +const $v0 = 8; +function isLowLevelRegister(register) { + return register <= $sp; +} +var SavedRegister; + +(function (SavedRegister) { + SavedRegister[SavedRegister["s0"] = 4] = "s0"; + SavedRegister[SavedRegister["s1"] = 5] = "s1"; +})(SavedRegister || (SavedRegister = {})); + +var TemporaryRegister; + +(function (TemporaryRegister) { + TemporaryRegister[TemporaryRegister["t0"] = 6] = "t0"; + TemporaryRegister[TemporaryRegister["t1"] = 7] = "t1"; +})(TemporaryRegister || (TemporaryRegister = {})); + +export { isMachineOp, isOp, SavedRegister, TemporaryRegister, isLowLevelRegister, $pc, $fp, $ra, $sp, $s0, $s1, $t0, $t1, $v0 }; diff --git a/ember-vendored-pr-19806/dependencies/@glimmer/wire-format.js b/ember-vendored-pr-19806/dependencies/@glimmer/wire-format.js new file mode 100644 index 0000000..927ed18 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@glimmer/wire-format.js @@ -0,0 +1,52 @@ +function is(variant) { + return function (value) { + return Array.isArray(value) && value[0] === variant; + }; +} // Statements + +const isFlushElement = is(12 +/* FlushElement */ +); +function isAttribute(val) { + return val[0] === 14 + /* StaticAttr */ + || val[0] === 15 + /* DynamicAttr */ + || val[0] === 22 + /* TrustingDynamicAttr */ + || val[0] === 16 + /* ComponentAttr */ + || val[0] === 24 + /* StaticComponentAttr */ + || val[0] === 23 + /* TrustingComponentAttr */ + || val[0] === 17 + /* AttrSplat */ + || val[0] === 4 + /* Modifier */ + ; +} +function isStringLiteral(expr) { + return typeof expr === 'string'; +} +function getStringFromValue(expr) { + return expr; +} +function isArgument(val) { + return val[0] === 21 + /* StaticArg */ + || val[0] === 20 + /* DynamicArg */ + ; +} +function isHelper(expr) { + return Array.isArray(expr) && expr[0] === 28 + /* Call */ + ; +} // Expressions + +const isGet = is(30 +/* GetSymbol */ +); + +export { is, isFlushElement, isAttribute, isStringLiteral, getStringFromValue, isArgument, isHelper, isGet }; diff --git a/ember-vendored-pr-19806/dependencies/@simple-dom/document.js b/ember-vendored-pr-19806/dependencies/@simple-dom/document.js new file mode 100644 index 0000000..738ea41 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/@simple-dom/document.js @@ -0,0 +1,365 @@ +const EMPTY_ATTRS = []; +function indexOfAttribute(attributes, namespaceURI, localName) { + for (let i = 0; i < attributes.length; i++) { + const attr = attributes[i]; + if (attr.namespaceURI === namespaceURI && attr.localName === localName) { + return i; + } + } + return -1; +} +function adjustAttrName(namespaceURI, localName) { + return namespaceURI === "http://www.w3.org/1999/xhtml" /* HTML */ ? localName.toLowerCase() : localName; +} +function getAttribute(attributes, namespaceURI, localName) { + const index = indexOfAttribute(attributes, namespaceURI, localName); + return index === -1 ? null : attributes[index].value; +} +function removeAttribute(attributes, namespaceURI, localName) { + const index = indexOfAttribute(attributes, namespaceURI, localName); + if (index !== -1) { + attributes.splice(index, 1); + } +} +// https://dom.spec.whatwg.org/#dom-element-setattributens +function setAttribute(element, namespaceURI, prefix, localName, value) { + if (typeof value !== 'string') { + value = '' + value; + } + let { attributes } = element; + if (attributes === EMPTY_ATTRS) { + attributes = element.attributes = []; + } + else { + const index = indexOfAttribute(attributes, namespaceURI, localName); + if (index !== -1) { + attributes[index].value = value; + return; + } + } + attributes.push({ + localName, + name: prefix === null ? localName : prefix + ':' + localName, + namespaceURI, + prefix, + specified: true, + value, + }); +} + +class ChildNodes { + constructor(node) { + this.node = node; + this.stale = true; + this._length = 0; + } + get length() { + if (this.stale) { + this.stale = false; + let len = 0; + let child = this.node.firstChild; + for (; child !== null; len++) { + this[len] = child; + child = child.nextSibling; + } + const oldLen = this._length; + this._length = len; + for (; len < oldLen; len++) { + delete this[len]; + } + } + return this._length; + } + item(index) { + return index < this.length ? this[index] : null; + } +} + +function cloneNode(node, deep) { + const clone = nodeFrom(node); + if (deep) { + let child = node.firstChild; + let nextChild = child; + while (child !== null) { + nextChild = child.nextSibling; + clone.appendChild(child.cloneNode(true)); + child = nextChild; + } + } + return clone; +} +function nodeFrom(node) { + let namespaceURI; + if (node.nodeType === 1 /* ELEMENT_NODE */) { + namespaceURI = node.namespaceURI; + } + const clone = new SimpleNodeImpl(node.ownerDocument, node.nodeType, node.nodeName, node.nodeValue, namespaceURI); + if (node.nodeType === 1 /* ELEMENT_NODE */) { + clone.attributes = copyAttrs(node.attributes); + } + return clone; +} +function copyAttrs(attrs) { + if (attrs === EMPTY_ATTRS) { + return EMPTY_ATTRS; + } + const copy = []; + for (let i = 0; i < attrs.length; i++) { + const attr = attrs[i]; + copy.push({ + localName: attr.localName, + name: attr.name, + namespaceURI: attr.namespaceURI, + prefix: attr.prefix, + specified: true, + value: attr.value, + }); + } + return copy; +} + +function insertBefore(parentNode, newChild, refChild) { + invalidate(parentNode); + insertBetween(parentNode, newChild, refChild === null ? parentNode.lastChild : refChild.previousSibling, refChild); +} +function removeChild(parentNode, oldChild) { + invalidate(parentNode); + removeBetween(parentNode, oldChild, oldChild.previousSibling, oldChild.nextSibling); +} +function invalidate(parentNode) { + const childNodes = parentNode._childNodes; + if (childNodes !== undefined) { + childNodes.stale = true; + } +} +function insertBetween(parentNode, newChild, previousSibling, nextSibling) { + if (newChild.nodeType === 11 /* DOCUMENT_FRAGMENT_NODE */) { + insertFragment(newChild, parentNode, previousSibling, nextSibling); + return; + } + if (newChild.parentNode !== null) { + removeChild(newChild.parentNode, newChild); + } + newChild.parentNode = parentNode; + newChild.previousSibling = previousSibling; + newChild.nextSibling = nextSibling; + if (previousSibling === null) { + parentNode.firstChild = newChild; + } + else { + previousSibling.nextSibling = newChild; + } + if (nextSibling === null) { + parentNode.lastChild = newChild; + } + else { + nextSibling.previousSibling = newChild; + } +} +function removeBetween(parentNode, oldChild, previousSibling, nextSibling) { + oldChild.parentNode = null; + oldChild.previousSibling = null; + oldChild.nextSibling = null; + if (previousSibling === null) { + parentNode.firstChild = nextSibling; + } + else { + previousSibling.nextSibling = nextSibling; + } + if (nextSibling === null) { + parentNode.lastChild = previousSibling; + } + else { + nextSibling.previousSibling = previousSibling; + } +} +function insertFragment(fragment, parentNode, previousSibling, nextSibling) { + const firstChild = fragment.firstChild; + if (firstChild === null) { + return; + } + fragment.firstChild = null; + fragment.lastChild = null; + let lastChild = firstChild; + let newChild = firstChild; + firstChild.previousSibling = previousSibling; + if (previousSibling === null) { + parentNode.firstChild = firstChild; + } + else { + previousSibling.nextSibling = firstChild; + } + while (newChild !== null) { + newChild.parentNode = parentNode; + lastChild = newChild; + newChild = newChild.nextSibling; + } + lastChild.nextSibling = nextSibling; + if (nextSibling === null) { + parentNode.lastChild = lastChild; + } + else { + nextSibling.previousSibling = lastChild; + } +} + +function parseQualifiedName(qualifiedName) { + let localName = qualifiedName; + let prefix = null; + const i = qualifiedName.indexOf(':'); + if (i !== -1) { + prefix = qualifiedName.slice(0, i); + localName = qualifiedName.slice(i + 1); + } + return [prefix, localName]; +} + +class SimpleNodeImpl { + constructor(ownerDocument, nodeType, nodeName, nodeValue, namespaceURI) { + this.ownerDocument = ownerDocument; + this.nodeType = nodeType; + this.nodeName = nodeName; + this.nodeValue = nodeValue; + this.namespaceURI = namespaceURI; + this.parentNode = null; + this.previousSibling = null; + this.nextSibling = null; + this.firstChild = null; + this.lastChild = null; + this.attributes = EMPTY_ATTRS; + /** + * @internal + */ + this._childNodes = undefined; + } + get tagName() { + return this.nodeName; + } + get childNodes() { + let children = this._childNodes; + if (children === undefined) { + children = this._childNodes = new ChildNodes(this); + } + return children; + } + cloneNode(deep) { + return cloneNode(this, deep === true); + } + appendChild(newChild) { + insertBefore(this, newChild, null); + return newChild; + } + insertBefore(newChild, refChild) { + insertBefore(this, newChild, refChild); + return newChild; + } + removeChild(oldChild) { + removeChild(this, oldChild); + return oldChild; + } + insertAdjacentHTML(position, html) { + const raw = new SimpleNodeImpl(this.ownerDocument, -1 /* RAW_NODE */, '#raw', html, void 0); + let parentNode; + let nextSibling; + switch (position) { + case 'beforebegin': + parentNode = this.parentNode; + nextSibling = this; + break; + case 'afterbegin': + parentNode = this; + nextSibling = this.firstChild; + break; + case 'beforeend': + parentNode = this; + nextSibling = null; + break; + case 'afterend': + parentNode = this.parentNode; + nextSibling = this.nextSibling; + break; + default: throw new Error('invalid position'); + } + if (parentNode === null) { + throw new Error(`${position} requires a parentNode`); + } + insertBefore(parentNode, raw, nextSibling); + } + getAttribute(name) { + const localName = adjustAttrName(this.namespaceURI, name); + return getAttribute(this.attributes, null, localName); + } + getAttributeNS(namespaceURI, localName) { + return getAttribute(this.attributes, namespaceURI, localName); + } + setAttribute(name, value) { + const localName = adjustAttrName(this.namespaceURI, name); + setAttribute(this, null, null, localName, value); + } + setAttributeNS(namespaceURI, qualifiedName, value) { + const [prefix, localName] = parseQualifiedName(qualifiedName); + setAttribute(this, namespaceURI, prefix, localName, value); + } + removeAttribute(name) { + const localName = adjustAttrName(this.namespaceURI, name); + removeAttribute(this.attributes, null, localName); + } + removeAttributeNS(namespaceURI, localName) { + removeAttribute(this.attributes, namespaceURI, localName); + } + get doctype() { + return this.firstChild; + } + get documentElement() { + return this.lastChild; + } + get head() { + return this.documentElement.firstChild; + } + get body() { + return this.documentElement.lastChild; + } + createElement(name) { + return new SimpleNodeImpl(this, 1 /* ELEMENT_NODE */, name.toUpperCase(), null, "http://www.w3.org/1999/xhtml" /* HTML */); + } + createElementNS(namespace, qualifiedName) { + // Node name is case-preserving in XML contexts, but returns canonical uppercase form in HTML contexts + // https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-104682815 + const nodeName = namespace === "http://www.w3.org/1999/xhtml" /* HTML */ ? qualifiedName.toUpperCase() : qualifiedName; + // we don't care to parse the qualified name because we only support HTML documents + // which don't support prefixed elements + return new SimpleNodeImpl(this, 1 /* ELEMENT_NODE */, nodeName, null, namespace); + } + createTextNode(text) { + return new SimpleNodeImpl(this, 3 /* TEXT_NODE */, '#text', text, void 0); + } + createComment(text) { + return new SimpleNodeImpl(this, 8 /* COMMENT_NODE */, '#comment', text, void 0); + } + /** + * Backwards compat + * @deprecated + */ + createRawHTMLSection(text) { + return new SimpleNodeImpl(this, -1 /* RAW_NODE */, '#raw', text, void 0); + } + createDocumentFragment() { + return new SimpleNodeImpl(this, 11 /* DOCUMENT_FRAGMENT_NODE */, '#document-fragment', null, void 0); + } +} + +function createHTMLDocument() { + // dom.d.ts types ownerDocument as Document but for a document ownerDocument is null + const document = new SimpleNodeImpl(null, 9 /* DOCUMENT_NODE */, '#document', null, "http://www.w3.org/1999/xhtml" /* HTML */); + const doctype = new SimpleNodeImpl(document, 10 /* DOCUMENT_TYPE_NODE */, 'html', null, "http://www.w3.org/1999/xhtml" /* HTML */); + const html = new SimpleNodeImpl(document, 1 /* ELEMENT_NODE */, 'HTML', null, "http://www.w3.org/1999/xhtml" /* HTML */); + const head = new SimpleNodeImpl(document, 1 /* ELEMENT_NODE */, 'HEAD', null, "http://www.w3.org/1999/xhtml" /* HTML */); + const body = new SimpleNodeImpl(document, 1 /* ELEMENT_NODE */, 'BODY', null, "http://www.w3.org/1999/xhtml" /* HTML */); + html.appendChild(head); + html.appendChild(body); + document.appendChild(doctype); + document.appendChild(html); + return document; +} + +export default createHTMLDocument; diff --git a/ember-vendored-pr-19806/dependencies/backburner.js b/ember-vendored-pr-19806/dependencies/backburner.js new file mode 100644 index 0000000..ddb5ff5 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/backburner.js @@ -0,0 +1,973 @@ +const SET_TIMEOUT = setTimeout; +const NOOP = () => { }; +function buildNext(flush) { + // Using "promises first" here to: + // + // 1) Ensure more consistent experience on browsers that + // have differently queued microtasks (separate queues for + // MutationObserver vs Promises). + // 2) Ensure better debugging experiences (it shows up in Chrome + // call stack as "Promise.then (async)") which is more consistent + // with user expectations + // + // When Promise is unavailable use MutationObserver (mostly so that we + // still get microtasks on IE11), and when neither MutationObserver and + // Promise are present use a plain old setTimeout. + if (typeof Promise === 'function') { + const autorunPromise = Promise.resolve(); + return () => autorunPromise.then(flush); + } + else if (typeof MutationObserver === 'function') { + let iterations = 0; + let observer = new MutationObserver(flush); + let node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + return () => { + iterations = ++iterations % 2; + node.data = '' + iterations; + return iterations; + }; + } + else { + return () => SET_TIMEOUT(flush, 0); + } +} +function buildPlatform(flush) { + let clearNext = NOOP; + return { + setTimeout(fn, ms) { + return setTimeout(fn, ms); + }, + clearTimeout(timerId) { + return clearTimeout(timerId); + }, + now() { + return Date.now(); + }, + next: buildNext(flush), + clearNext, + }; +} + +const NUMBER = /\d+/; +const TIMERS_OFFSET = 6; +function isCoercableNumber(suspect) { + let type = typeof suspect; + return type === 'number' && suspect === suspect || type === 'string' && NUMBER.test(suspect); +} +function getOnError(options) { + return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); +} +function findItem(target, method, collection) { + let index = -1; + for (let i = 0, l = collection.length; i < l; i += 4) { + if (collection[i] === target && collection[i + 1] === method) { + index = i; + break; + } + } + return index; +} +function findTimerItem(target, method, collection) { + let index = -1; + for (let i = 2, l = collection.length; i < l; i += 6) { + if (collection[i] === target && collection[i + 1] === method) { + index = i - 2; + break; + } + } + return index; +} +function getQueueItems(items, queueItemLength, queueItemPositionOffset = 0) { + let queueItems = []; + for (let i = 0; i < items.length; i += queueItemLength) { + let maybeError = items[i + 3 /* stack */ + queueItemPositionOffset]; + let queueItem = { + target: items[i + 0 /* target */ + queueItemPositionOffset], + method: items[i + 1 /* method */ + queueItemPositionOffset], + args: items[i + 2 /* args */ + queueItemPositionOffset], + stack: maybeError !== undefined && 'stack' in maybeError ? maybeError.stack : '' + }; + queueItems.push(queueItem); + } + return queueItems; +} + +function binarySearch(time, timers) { + let start = 0; + let end = timers.length - TIMERS_OFFSET; + let middle; + let l; + while (start < end) { + // since timers is an array of pairs 'l' will always + // be an integer + l = (end - start) / TIMERS_OFFSET; + // compensate for the index in case even number + // of pairs inside timers + middle = start + l - (l % TIMERS_OFFSET); + if (time >= timers[middle]) { + start = middle + TIMERS_OFFSET; + } + else { + end = middle; + } + } + return (time >= timers[start]) ? start + TIMERS_OFFSET : start; +} + +const QUEUE_ITEM_LENGTH = 4; +class Queue { + constructor(name, options = {}, globalOptions = {}) { + this._queueBeingFlushed = []; + this.targetQueues = new Map(); + this.index = 0; + this._queue = []; + this.name = name; + this.options = options; + this.globalOptions = globalOptions; + } + stackFor(index) { + if (index < this._queue.length) { + let entry = this._queue[index * 3 + QUEUE_ITEM_LENGTH]; + if (entry) { + return entry.stack; + } + else { + return null; + } + } + } + flush(sync) { + let { before, after } = this.options; + let target; + let method; + let args; + let errorRecordedForStack; + this.targetQueues.clear(); + if (this._queueBeingFlushed.length === 0) { + this._queueBeingFlushed = this._queue; + this._queue = []; + } + if (before !== undefined) { + before(); + } + let invoke; + let queueItems = this._queueBeingFlushed; + if (queueItems.length > 0) { + let onError = getOnError(this.globalOptions); + invoke = onError ? this.invokeWithOnError : this.invoke; + for (let i = this.index; i < queueItems.length; i += QUEUE_ITEM_LENGTH) { + this.index += QUEUE_ITEM_LENGTH; + method = queueItems[i + 1]; + // method could have been nullified / canceled during flush + if (method !== null) { + // + // ** Attention intrepid developer ** + // + // To find out the stack of this task when it was scheduled onto + // the run loop, add the following to your app.js: + // + // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production. + // + // Once that is in place, when you are at a breakpoint and navigate + // here in the stack explorer, you can look at `errorRecordedForStack.stack`, + // which will be the captured stack when this job was scheduled. + // + // One possible long-term solution is the following Chrome issue: + // https://bugs.chromium.org/p/chromium/issues/detail?id=332624 + // + target = queueItems[i]; + args = queueItems[i + 2]; + errorRecordedForStack = queueItems[i + 3]; // Debugging assistance + invoke(target, method, args, onError, errorRecordedForStack); + } + if (this.index !== this._queueBeingFlushed.length && + this.globalOptions.mustYield && this.globalOptions.mustYield()) { + return 1 /* Pause */; + } + } + } + if (after !== undefined) { + after(); + } + this._queueBeingFlushed.length = 0; + this.index = 0; + if (sync !== false && this._queue.length > 0) { + // check if new items have been added + this.flush(true); + } + } + hasWork() { + return this._queueBeingFlushed.length > 0 || this._queue.length > 0; + } + cancel({ target, method }) { + let queue = this._queue; + let targetQueueMap = this.targetQueues.get(target); + if (targetQueueMap !== undefined) { + targetQueueMap.delete(method); + } + let index = findItem(target, method, queue); + if (index > -1) { + queue.splice(index, QUEUE_ITEM_LENGTH); + return true; + } + // if not found in current queue + // could be in the queue that is being flushed + queue = this._queueBeingFlushed; + index = findItem(target, method, queue); + if (index > -1) { + queue[index + 1] = null; + return true; + } + return false; + } + push(target, method, args, stack) { + this._queue.push(target, method, args, stack); + return { + queue: this, + target, + method + }; + } + pushUnique(target, method, args, stack) { + let localQueueMap = this.targetQueues.get(target); + if (localQueueMap === undefined) { + localQueueMap = new Map(); + this.targetQueues.set(target, localQueueMap); + } + let index = localQueueMap.get(method); + if (index === undefined) { + let queueIndex = this._queue.push(target, method, args, stack) - QUEUE_ITEM_LENGTH; + localQueueMap.set(method, queueIndex); + } + else { + let queue = this._queue; + queue[index + 2] = args; // replace args + queue[index + 3] = stack; // replace stack + } + return { + queue: this, + target, + method + }; + } + _getDebugInfo(debugEnabled) { + if (debugEnabled) { + let debugInfo = getQueueItems(this._queue, QUEUE_ITEM_LENGTH); + return debugInfo; + } + return undefined; + } + invoke(target, method, args /*, onError, errorRecordedForStack */) { + if (args === undefined) { + method.call(target); + } + else { + method.apply(target, args); + } + } + invokeWithOnError(target, method, args, onError, errorRecordedForStack) { + try { + if (args === undefined) { + method.call(target); + } + else { + method.apply(target, args); + } + } + catch (error) { + onError(error, errorRecordedForStack); + } + } +} + +class DeferredActionQueues { + constructor(queueNames = [], options) { + this.queues = {}; + this.queueNameIndex = 0; + this.queueNames = queueNames; + queueNames.reduce(function (queues, queueName) { + queues[queueName] = new Queue(queueName, options[queueName], options); + return queues; + }, this.queues); + } + /** + * @method schedule + * @param {String} queueName + * @param {Any} target + * @param {Any} method + * @param {Any} args + * @param {Boolean} onceFlag + * @param {Any} stack + * @return queue + */ + schedule(queueName, target, method, args, onceFlag, stack) { + let queues = this.queues; + let queue = queues[queueName]; + if (queue === undefined) { + throw new Error(`You attempted to schedule an action in a queue (${queueName}) that doesn\'t exist`); + } + if (method === undefined || method === null) { + throw new Error(`You attempted to schedule an action in a queue (${queueName}) for a method that doesn\'t exist`); + } + this.queueNameIndex = 0; + if (onceFlag) { + return queue.pushUnique(target, method, args, stack); + } + else { + return queue.push(target, method, args, stack); + } + } + /** + * DeferredActionQueues.flush() calls Queue.flush() + * + * @method flush + * @param {Boolean} fromAutorun + */ + flush(fromAutorun = false) { + let queue; + let queueName; + let numberOfQueues = this.queueNames.length; + while (this.queueNameIndex < numberOfQueues) { + queueName = this.queueNames[this.queueNameIndex]; + queue = this.queues[queueName]; + if (queue.hasWork() === false) { + this.queueNameIndex++; + if (fromAutorun && this.queueNameIndex < numberOfQueues) { + return 1 /* Pause */; + } + } + else { + if (queue.flush(false /* async */) === 1 /* Pause */) { + return 1 /* Pause */; + } + } + } + } + /** + * Returns debug information for the current queues. + * + * @method _getDebugInfo + * @param {Boolean} debugEnabled + * @returns {IDebugInfo | undefined} + */ + _getDebugInfo(debugEnabled) { + if (debugEnabled) { + let debugInfo = {}; + let queue; + let queueName; + let numberOfQueues = this.queueNames.length; + let i = 0; + while (i < numberOfQueues) { + queueName = this.queueNames[i]; + queue = this.queues[queueName]; + debugInfo[queueName] = queue._getDebugInfo(debugEnabled); + i++; + } + return debugInfo; + } + return; + } +} + +function iteratorDrain (fn) { + let iterator = fn(); + let result = iterator.next(); + while (result.done === false) { + result.value(); + result = iterator.next(); + } +} + +const noop = function () { }; +const DISABLE_SCHEDULE = Object.freeze([]); +function parseArgs() { + let length = arguments.length; + let args; + let method; + let target; + if (length === 0) ; + else if (length === 1) { + target = null; + method = arguments[0]; + } + else { + let argsIndex = 2; + let methodOrTarget = arguments[0]; + let methodOrArgs = arguments[1]; + let type = typeof methodOrArgs; + if (type === 'function') { + target = methodOrTarget; + method = methodOrArgs; + } + else if (methodOrTarget !== null && type === 'string' && methodOrArgs in methodOrTarget) { + target = methodOrTarget; + method = target[methodOrArgs]; + } + else if (typeof methodOrTarget === 'function') { + argsIndex = 1; + target = null; + method = methodOrTarget; + } + if (length > argsIndex) { + let len = length - argsIndex; + args = new Array(len); + for (let i = 0; i < len; i++) { + args[i] = arguments[i + argsIndex]; + } + } + } + return [target, method, args]; +} +function parseTimerArgs() { + let [target, method, args] = parseArgs(...arguments); + let wait = 0; + let length = args !== undefined ? args.length : 0; + if (length > 0) { + let last = args[length - 1]; + if (isCoercableNumber(last)) { + wait = parseInt(args.pop(), 10); + } + } + return [target, method, args, wait]; +} +function parseDebounceArgs() { + let target; + let method; + let isImmediate; + let args; + let wait; + if (arguments.length === 2) { + method = arguments[0]; + wait = arguments[1]; + target = null; + } + else { + [target, method, args] = parseArgs(...arguments); + if (args === undefined) { + wait = 0; + } + else { + wait = args.pop(); + if (!isCoercableNumber(wait)) { + isImmediate = wait === true; + wait = args.pop(); + } + } + } + wait = parseInt(wait, 10); + return [target, method, args, wait, isImmediate]; +} +let UUID = 0; +let beginCount = 0; +let endCount = 0; +let beginEventCount = 0; +let endEventCount = 0; +let runCount = 0; +let joinCount = 0; +let deferCount = 0; +let scheduleCount = 0; +let scheduleIterableCount = 0; +let deferOnceCount = 0; +let scheduleOnceCount = 0; +let setTimeoutCount = 0; +let laterCount = 0; +let throttleCount = 0; +let debounceCount = 0; +let cancelTimersCount = 0; +let cancelCount = 0; +let autorunsCreatedCount = 0; +let autorunsCompletedCount = 0; +let deferredActionQueuesCreatedCount = 0; +let nestedDeferredActionQueuesCreated = 0; +class Backburner { + constructor(queueNames, options) { + this.DEBUG = false; + this.currentInstance = null; + this.instanceStack = []; + this._eventCallbacks = { + end: [], + begin: [] + }; + this._timerTimeoutId = null; + this._timers = []; + this._autorun = false; + this._autorunStack = null; + this.queueNames = queueNames; + this.options = options || {}; + if (typeof this.options.defaultQueue === 'string') { + this._defaultQueue = this.options.defaultQueue; + } + else { + this._defaultQueue = this.queueNames[0]; + } + this._onBegin = this.options.onBegin || noop; + this._onEnd = this.options.onEnd || noop; + this._boundRunExpiredTimers = this._runExpiredTimers.bind(this); + this._boundAutorunEnd = () => { + autorunsCompletedCount++; + // if the autorun was already flushed, do nothing + if (this._autorun === false) { + return; + } + this._autorun = false; + this._autorunStack = null; + this._end(true /* fromAutorun */); + }; + let builder = this.options._buildPlatform || buildPlatform; + this._platform = builder(this._boundAutorunEnd); + } + get counters() { + return { + begin: beginCount, + end: endCount, + events: { + begin: beginEventCount, + end: endEventCount, + }, + autoruns: { + created: autorunsCreatedCount, + completed: autorunsCompletedCount, + }, + run: runCount, + join: joinCount, + defer: deferCount, + schedule: scheduleCount, + scheduleIterable: scheduleIterableCount, + deferOnce: deferOnceCount, + scheduleOnce: scheduleOnceCount, + setTimeout: setTimeoutCount, + later: laterCount, + throttle: throttleCount, + debounce: debounceCount, + cancelTimers: cancelTimersCount, + cancel: cancelCount, + loops: { + total: deferredActionQueuesCreatedCount, + nested: nestedDeferredActionQueuesCreated, + }, + }; + } + get defaultQueue() { + return this._defaultQueue; + } + /* + @method begin + @return instantiated class DeferredActionQueues + */ + begin() { + beginCount++; + let options = this.options; + let previousInstance = this.currentInstance; + let current; + if (this._autorun !== false) { + current = previousInstance; + this._cancelAutorun(); + } + else { + if (previousInstance !== null) { + nestedDeferredActionQueuesCreated++; + this.instanceStack.push(previousInstance); + } + deferredActionQueuesCreatedCount++; + current = this.currentInstance = new DeferredActionQueues(this.queueNames, options); + beginEventCount++; + this._trigger('begin', current, previousInstance); + } + this._onBegin(current, previousInstance); + return current; + } + end() { + endCount++; + this._end(false); + } + on(eventName, callback) { + if (typeof callback !== 'function') { + throw new TypeError(`Callback must be a function`); + } + let callbacks = this._eventCallbacks[eventName]; + if (callbacks !== undefined) { + callbacks.push(callback); + } + else { + throw new TypeError(`Cannot on() event ${eventName} because it does not exist`); + } + } + off(eventName, callback) { + let callbacks = this._eventCallbacks[eventName]; + if (!eventName || callbacks === undefined) { + throw new TypeError(`Cannot off() event ${eventName} because it does not exist`); + } + let callbackFound = false; + if (callback) { + for (let i = 0; i < callbacks.length; i++) { + if (callbacks[i] === callback) { + callbackFound = true; + callbacks.splice(i, 1); + i--; + } + } + } + if (!callbackFound) { + throw new TypeError(`Cannot off() callback that does not exist`); + } + } + run() { + runCount++; + let [target, method, args] = parseArgs(...arguments); + return this._run(target, method, args); + } + join() { + joinCount++; + let [target, method, args] = parseArgs(...arguments); + return this._join(target, method, args); + } + /** + * @deprecated please use schedule instead. + */ + defer(queueName, target, method, ...args) { + deferCount++; + return this.schedule(queueName, target, method, ...args); + } + schedule(queueName, ..._args) { + scheduleCount++; + let [target, method, args] = parseArgs(..._args); + let stack = this.DEBUG ? new Error() : undefined; + return this._ensureInstance().schedule(queueName, target, method, args, false, stack); + } + /* + Defer the passed iterable of functions to run inside the specified queue. + + @method scheduleIterable + @param {String} queueName + @param {Iterable} an iterable of functions to execute + @return method result + */ + scheduleIterable(queueName, iterable) { + scheduleIterableCount++; + let stack = this.DEBUG ? new Error() : undefined; + return this._ensureInstance().schedule(queueName, null, iteratorDrain, [iterable], false, stack); + } + /** + * @deprecated please use scheduleOnce instead. + */ + deferOnce(queueName, target, method, ...args) { + deferOnceCount++; + return this.scheduleOnce(queueName, target, method, ...args); + } + scheduleOnce(queueName, ..._args) { + scheduleOnceCount++; + let [target, method, args] = parseArgs(..._args); + let stack = this.DEBUG ? new Error() : undefined; + return this._ensureInstance().schedule(queueName, target, method, args, true, stack); + } + setTimeout() { + setTimeoutCount++; + return this.later(...arguments); + } + later() { + laterCount++; + let [target, method, args, wait] = parseTimerArgs(...arguments); + return this._later(target, method, args, wait); + } + throttle() { + throttleCount++; + let [target, method, args, wait, isImmediate = true] = parseDebounceArgs(...arguments); + let index = findTimerItem(target, method, this._timers); + let timerId; + if (index === -1) { + timerId = this._later(target, method, isImmediate ? DISABLE_SCHEDULE : args, wait); + if (isImmediate) { + this._join(target, method, args); + } + } + else { + timerId = this._timers[index + 1]; + let argIndex = index + 4; + if (this._timers[argIndex] !== DISABLE_SCHEDULE) { + this._timers[argIndex] = args; + } + } + return timerId; + } + debounce() { + debounceCount++; + let [target, method, args, wait, isImmediate = false] = parseDebounceArgs(...arguments); + let _timers = this._timers; + let index = findTimerItem(target, method, _timers); + let timerId; + if (index === -1) { + timerId = this._later(target, method, isImmediate ? DISABLE_SCHEDULE : args, wait); + if (isImmediate) { + this._join(target, method, args); + } + } + else { + let executeAt = this._platform.now() + wait; + let argIndex = index + 4; + if (_timers[argIndex] === DISABLE_SCHEDULE) { + args = DISABLE_SCHEDULE; + } + timerId = _timers[index + 1]; + let i = binarySearch(executeAt, _timers); + if ((index + TIMERS_OFFSET) === i) { + _timers[index] = executeAt; + _timers[argIndex] = args; + } + else { + let stack = this._timers[index + 5]; + this._timers.splice(i, 0, executeAt, timerId, target, method, args, stack); + this._timers.splice(index, TIMERS_OFFSET); + } + if (index === 0) { + this._reinstallTimerTimeout(); + } + } + return timerId; + } + cancelTimers() { + cancelTimersCount++; + this._clearTimerTimeout(); + this._timers = []; + this._cancelAutorun(); + } + hasTimers() { + return this._timers.length > 0 || this._autorun; + } + cancel(timer) { + cancelCount++; + if (timer === null || timer === undefined) { + return false; + } + let timerType = typeof timer; + if (timerType === 'number') { // we're cancelling a setTimeout or throttle or debounce + return this._cancelLaterTimer(timer); + } + else if (timerType === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce + return timer.queue.cancel(timer); + } + return false; + } + ensureInstance() { + this._ensureInstance(); + } + /** + * Returns debug information related to the current instance of Backburner + * + * @method getDebugInfo + * @returns {Object | undefined} Will return and Object containing debug information if + * the DEBUG flag is set to true on the current instance of Backburner, else undefined. + */ + getDebugInfo() { + if (this.DEBUG) { + return { + autorun: this._autorunStack, + counters: this.counters, + timers: getQueueItems(this._timers, TIMERS_OFFSET, 2), + instanceStack: [this.currentInstance, ...this.instanceStack] + .map((deferredActionQueue) => deferredActionQueue && deferredActionQueue._getDebugInfo(this.DEBUG)) + }; + } + return undefined; + } + _end(fromAutorun) { + let currentInstance = this.currentInstance; + let nextInstance = null; + if (currentInstance === null) { + throw new Error(`end called without begin`); + } + // Prevent double-finally bug in Safari 6.0.2 and iOS 6 + // This bug appears to be resolved in Safari 6.0.5 and iOS 7 + let finallyAlreadyCalled = false; + let result; + try { + result = currentInstance.flush(fromAutorun); + } + finally { + if (!finallyAlreadyCalled) { + finallyAlreadyCalled = true; + if (result === 1 /* Pause */) { + const plannedNextQueue = this.queueNames[currentInstance.queueNameIndex]; + this._scheduleAutorun(plannedNextQueue); + } + else { + this.currentInstance = null; + if (this.instanceStack.length > 0) { + nextInstance = this.instanceStack.pop(); + this.currentInstance = nextInstance; + } + this._trigger('end', currentInstance, nextInstance); + this._onEnd(currentInstance, nextInstance); + } + } + } + } + _join(target, method, args) { + if (this.currentInstance === null) { + return this._run(target, method, args); + } + if (target === undefined && args === undefined) { + return method(); + } + else { + return method.apply(target, args); + } + } + _run(target, method, args) { + let onError = getOnError(this.options); + this.begin(); + if (onError) { + try { + return method.apply(target, args); + } + catch (error) { + onError(error); + } + finally { + this.end(); + } + } + else { + try { + return method.apply(target, args); + } + finally { + this.end(); + } + } + } + _cancelAutorun() { + if (this._autorun) { + this._platform.clearNext(); + this._autorun = false; + this._autorunStack = null; + } + } + _later(target, method, args, wait) { + let stack = this.DEBUG ? new Error() : undefined; + let executeAt = this._platform.now() + wait; + let id = UUID++; + if (this._timers.length === 0) { + this._timers.push(executeAt, id, target, method, args, stack); + this._installTimerTimeout(); + } + else { + // find position to insert + let i = binarySearch(executeAt, this._timers); + this._timers.splice(i, 0, executeAt, id, target, method, args, stack); + // always reinstall since it could be out of sync + this._reinstallTimerTimeout(); + } + return id; + } + _cancelLaterTimer(timer) { + for (let i = 1; i < this._timers.length; i += TIMERS_OFFSET) { + if (this._timers[i] === timer) { + this._timers.splice(i - 1, TIMERS_OFFSET); + if (i === 1) { + this._reinstallTimerTimeout(); + } + return true; + } + } + return false; + } + /** + Trigger an event. Supports up to two arguments. Designed around + triggering transition events from one run loop instance to the + next, which requires an argument for the instance and then + an argument for the next instance. + + @private + @method _trigger + @param {String} eventName + @param {any} arg1 + @param {any} arg2 + */ + _trigger(eventName, arg1, arg2) { + let callbacks = this._eventCallbacks[eventName]; + if (callbacks !== undefined) { + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](arg1, arg2); + } + } + } + _runExpiredTimers() { + this._timerTimeoutId = null; + if (this._timers.length > 0) { + this.begin(); + this._scheduleExpiredTimers(); + this.end(); + } + } + _scheduleExpiredTimers() { + let timers = this._timers; + let i = 0; + let l = timers.length; + let defaultQueue = this._defaultQueue; + let n = this._platform.now(); + for (; i < l; i += TIMERS_OFFSET) { + let executeAt = timers[i]; + if (executeAt > n) { + break; + } + let args = timers[i + 4]; + if (args !== DISABLE_SCHEDULE) { + let target = timers[i + 2]; + let method = timers[i + 3]; + let stack = timers[i + 5]; + this.currentInstance.schedule(defaultQueue, target, method, args, false, stack); + } + } + timers.splice(0, i); + this._installTimerTimeout(); + } + _reinstallTimerTimeout() { + this._clearTimerTimeout(); + this._installTimerTimeout(); + } + _clearTimerTimeout() { + if (this._timerTimeoutId === null) { + return; + } + this._platform.clearTimeout(this._timerTimeoutId); + this._timerTimeoutId = null; + } + _installTimerTimeout() { + if (this._timers.length === 0) { + return; + } + let minExpiresAt = this._timers[0]; + let n = this._platform.now(); + let wait = Math.max(0, minExpiresAt - n); + this._timerTimeoutId = this._platform.setTimeout(this._boundRunExpiredTimers, wait); + } + _ensureInstance() { + let currentInstance = this.currentInstance; + if (currentInstance === null) { + this._autorunStack = this.DEBUG ? new Error() : undefined; + currentInstance = this.begin(); + this._scheduleAutorun(this.queueNames[0]); + } + return currentInstance; + } + _scheduleAutorun(plannedNextQueue) { + autorunsCreatedCount++; + const next = this._platform.next; + const flush = this.options.flush; + if (flush) { + flush(plannedNextQueue, next); + } + else { + next(); + } + this._autorun = true; + } +} +Backburner.Queue = Queue; +Backburner.buildPlatform = buildPlatform; +Backburner.buildNext = buildNext; + +export default Backburner; +export { buildPlatform }; +//# sourceMappingURL=backburner.js.map diff --git a/ember-vendored-pr-19806/dependencies/dag-map.js b/ember-vendored-pr-19806/dependencies/dag-map.js new file mode 100644 index 0000000..bd85937 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/dag-map.js @@ -0,0 +1,209 @@ +/** + * A topologically ordered map of key/value pairs with a simple API for adding constraints. + * + * Edges can forward reference keys that have not been added yet (the forward reference will + * map the key to undefined). + */ +var DAG = (function () { + function DAG() { + this._vertices = new Vertices(); + } + /** + * Adds a key/value pair with dependencies on other key/value pairs. + * + * @public + * @param key The key of the vertex to be added. + * @param value The value of that vertex. + * @param before A key or array of keys of the vertices that must + * be visited before this vertex. + * @param after An string or array of strings with the keys of the + * vertices that must be after this vertex is visited. + */ + DAG.prototype.add = function (key, value, before, after) { + if (!key) + throw new Error('argument `key` is required'); + var vertices = this._vertices; + var v = vertices.add(key); + v.val = value; + if (before) { + if (typeof before === "string") { + vertices.addEdge(v, vertices.add(before)); + } + else { + for (var i = 0; i < before.length; i++) { + vertices.addEdge(v, vertices.add(before[i])); + } + } + } + if (after) { + if (typeof after === "string") { + vertices.addEdge(vertices.add(after), v); + } + else { + for (var i = 0; i < after.length; i++) { + vertices.addEdge(vertices.add(after[i]), v); + } + } + } + }; + /** + * @deprecated please use add. + */ + DAG.prototype.addEdges = function (key, value, before, after) { + this.add(key, value, before, after); + }; + /** + * Visits key/value pairs in topological order. + * + * @public + * @param callback The function to be invoked with each key/value. + */ + DAG.prototype.each = function (callback) { + this._vertices.walk(callback); + }; + /** + * @deprecated please use each. + */ + DAG.prototype.topsort = function (callback) { + this.each(callback); + }; + return DAG; +}()); +export default DAG; +/** @private */ +var Vertices = (function () { + function Vertices() { + this.length = 0; + this.stack = new IntStack(); + this.path = new IntStack(); + this.result = new IntStack(); + } + Vertices.prototype.add = function (key) { + if (!key) + throw new Error("missing key"); + var l = this.length | 0; + var vertex; + for (var i = 0; i < l; i++) { + vertex = this[i]; + if (vertex.key === key) + return vertex; + } + this.length = l + 1; + return this[l] = { + idx: l, + key: key, + val: undefined, + out: false, + flag: false, + length: 0 + }; + }; + Vertices.prototype.addEdge = function (v, w) { + this.check(v, w.key); + var l = w.length | 0; + for (var i = 0; i < l; i++) { + if (w[i] === v.idx) + return; + } + w.length = l + 1; + w[l] = v.idx; + v.out = true; + }; + Vertices.prototype.walk = function (cb) { + this.reset(); + for (var i = 0; i < this.length; i++) { + var vertex = this[i]; + if (vertex.out) + continue; + this.visit(vertex, ""); + } + this.each(this.result, cb); + }; + Vertices.prototype.check = function (v, w) { + if (v.key === w) { + throw new Error("cycle detected: " + w + " <- " + w); + } + // quick check + if (v.length === 0) + return; + // shallow check + for (var i = 0; i < v.length; i++) { + var key = this[v[i]].key; + if (key === w) { + throw new Error("cycle detected: " + w + " <- " + v.key + " <- " + w); + } + } + // deep check + this.reset(); + this.visit(v, w); + if (this.path.length > 0) { + var msg_1 = "cycle detected: " + w; + this.each(this.path, function (key) { + msg_1 += " <- " + key; + }); + throw new Error(msg_1); + } + }; + Vertices.prototype.reset = function () { + this.stack.length = 0; + this.path.length = 0; + this.result.length = 0; + for (var i = 0, l = this.length; i < l; i++) { + this[i].flag = false; + } + }; + Vertices.prototype.visit = function (start, search) { + var _a = this, stack = _a.stack, path = _a.path, result = _a.result; + stack.push(start.idx); + while (stack.length) { + var index = stack.pop() | 0; + if (index >= 0) { + // enter + var vertex = this[index]; + if (vertex.flag) + continue; + vertex.flag = true; + path.push(index); + if (search === vertex.key) + break; + // push exit + stack.push(~index); + this.pushIncoming(vertex); + } + else { + // exit + path.pop(); + result.push(~index); + } + } + }; + Vertices.prototype.pushIncoming = function (incomming) { + var stack = this.stack; + for (var i = incomming.length - 1; i >= 0; i--) { + var index = incomming[i]; + if (!this[index].flag) { + stack.push(index); + } + } + }; + Vertices.prototype.each = function (indices, cb) { + for (var i = 0, l = indices.length; i < l; i++) { + var vertex = this[indices[i]]; + cb(vertex.key, vertex.val); + } + }; + return Vertices; +}()); +/** @private */ +var IntStack = (function () { + function IntStack() { + this.length = 0; + } + IntStack.prototype.push = function (n) { + this[this.length++] = n | 0; + }; + IntStack.prototype.pop = function () { + return this[--this.length] | 0; + }; + return IntStack; +}()); diff --git a/ember-vendored-pr-19806/dependencies/route-recognizer.js b/ember-vendored-pr-19806/dependencies/route-recognizer.js new file mode 100644 index 0000000..8910ff8 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/route-recognizer.js @@ -0,0 +1,685 @@ +var createObject = Object.create; +function createMap() { + var map = createObject(null); + map["__"] = undefined; + delete map["__"]; + return map; +} + +var Target = function Target(path, matcher, delegate) { + this.path = path; + this.matcher = matcher; + this.delegate = delegate; +}; +Target.prototype.to = function to (target, callback) { + var delegate = this.delegate; + if (delegate && delegate.willAddRoute) { + target = delegate.willAddRoute(this.matcher.target, target); + } + this.matcher.add(this.path, target); + if (callback) { + if (callback.length === 0) { + throw new Error("You must have an argument in the function passed to `to`"); + } + this.matcher.addChild(this.path, target, callback, this.delegate); + } +}; +var Matcher = function Matcher(target) { + this.routes = createMap(); + this.children = createMap(); + this.target = target; +}; +Matcher.prototype.add = function add (path, target) { + this.routes[path] = target; +}; +Matcher.prototype.addChild = function addChild (path, target, callback, delegate) { + var matcher = new Matcher(target); + this.children[path] = matcher; + var match = generateMatch(path, matcher, delegate); + if (delegate && delegate.contextEntered) { + delegate.contextEntered(target, match); + } + callback(match); +}; +function generateMatch(startingPath, matcher, delegate) { + function match(path, callback) { + var fullPath = startingPath + path; + if (callback) { + callback(generateMatch(fullPath, matcher, delegate)); + } + else { + return new Target(fullPath, matcher, delegate); + } + } + + return match; +} +function addRoute(routeArray, path, handler) { + var len = 0; + for (var i = 0; i < routeArray.length; i++) { + len += routeArray[i].path.length; + } + path = path.substr(len); + var route = { path: path, handler: handler }; + routeArray.push(route); +} +function eachRoute(baseRoute, matcher, callback, binding) { + var routes = matcher.routes; + var paths = Object.keys(routes); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + var routeArray = baseRoute.slice(); + addRoute(routeArray, path, routes[path]); + var nested = matcher.children[path]; + if (nested) { + eachRoute(routeArray, nested, callback, binding); + } + else { + callback.call(binding, routeArray); + } + } +} +var map = function (callback, addRouteCallback) { + var matcher = new Matcher(); + callback(generateMatch("", matcher, this.delegate)); + eachRoute([], matcher, function (routes) { + if (addRouteCallback) { + addRouteCallback(this, routes); + } + else { + this.add(routes); + } + }, this); +}; + +// Normalizes percent-encoded values in `path` to upper-case and decodes percent-encoded +// values that are not reserved (i.e., unicode characters, emoji, etc). The reserved +// chars are "/" and "%". +// Safe to call multiple times on the same path. +// Normalizes percent-encoded values in `path` to upper-case and decodes percent-encoded +function normalizePath(path) { + return path.split("/") + .map(normalizeSegment) + .join("/"); +} +// We want to ensure the characters "%" and "/" remain in percent-encoded +// form when normalizing paths, so replace them with their encoded form after +// decoding the rest of the path +var SEGMENT_RESERVED_CHARS = /%|\//g; +function normalizeSegment(segment) { + if (segment.length < 3 || segment.indexOf("%") === -1) + { return segment; } + return decodeURIComponent(segment).replace(SEGMENT_RESERVED_CHARS, encodeURIComponent); +} +// We do not want to encode these characters when generating dynamic path segments +// See https://tools.ietf.org/html/rfc3986#section-3.3 +// sub-delims: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" +// others allowed by RFC 3986: ":", "@" +// +// First encode the entire path segment, then decode any of the encoded special chars. +// +// The chars "!", "'", "(", ")", "*" do not get changed by `encodeURIComponent`, +// so the possible encoded chars are: +// ['%24', '%26', '%2B', '%2C', '%3B', '%3D', '%3A', '%40']. +var PATH_SEGMENT_ENCODINGS = /%(?:2(?:4|6|B|C)|3(?:B|D|A)|40)/g; +function encodePathSegment(str) { + return encodeURIComponent(str).replace(PATH_SEGMENT_ENCODINGS, decodeURIComponent); +} + +var escapeRegex = /(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\)/g; +var isArray = Array.isArray; +var hasOwnProperty = Object.prototype.hasOwnProperty; +function getParam(params, key) { + if (typeof params !== "object" || params === null) { + throw new Error("You must pass an object as the second argument to `generate`."); + } + if (!hasOwnProperty.call(params, key)) { + throw new Error("You must provide param `" + key + "` to `generate`."); + } + var value = params[key]; + var str = typeof value === "string" ? value : "" + value; + if (str.length === 0) { + throw new Error("You must provide a param `" + key + "`."); + } + return str; +} +var eachChar = []; +eachChar[0 /* Static */] = function (segment, currentState) { + var state = currentState; + var value = segment.value; + for (var i = 0; i < value.length; i++) { + var ch = value.charCodeAt(i); + state = state.put(ch, false, false); + } + return state; +}; +eachChar[1 /* Dynamic */] = function (_, currentState) { + return currentState.put(47 /* SLASH */, true, true); +}; +eachChar[2 /* Star */] = function (_, currentState) { + return currentState.put(-1 /* ANY */, false, true); +}; +eachChar[4 /* Epsilon */] = function (_, currentState) { + return currentState; +}; +var regex = []; +regex[0 /* Static */] = function (segment) { + return segment.value.replace(escapeRegex, "\\$1"); +}; +regex[1 /* Dynamic */] = function () { + return "([^/]+)"; +}; +regex[2 /* Star */] = function () { + return "(.+)"; +}; +regex[4 /* Epsilon */] = function () { + return ""; +}; +var generate = []; +generate[0 /* Static */] = function (segment) { + return segment.value; +}; +generate[1 /* Dynamic */] = function (segment, params) { + var value = getParam(params, segment.value); + if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS) { + return encodePathSegment(value); + } + else { + return value; + } +}; +generate[2 /* Star */] = function (segment, params) { + return getParam(params, segment.value); +}; +generate[4 /* Epsilon */] = function () { + return ""; +}; +var EmptyObject = Object.freeze({}); +var EmptyArray = Object.freeze([]); +// The `names` will be populated with the paramter name for each dynamic/star +// segment. `shouldDecodes` will be populated with a boolean for each dyanamic/star +// segment, indicating whether it should be decoded during recognition. +function parse(segments, route, types) { + // normalize route as not starting with a "/". Recognition will + // also normalize. + if (route.length > 0 && route.charCodeAt(0) === 47 /* SLASH */) { + route = route.substr(1); + } + var parts = route.split("/"); + var names = undefined; + var shouldDecodes = undefined; + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + var flags = 0; + var type = 0; + if (part === "") { + type = 4 /* Epsilon */; + } + else if (part.charCodeAt(0) === 58 /* COLON */) { + type = 1 /* Dynamic */; + } + else if (part.charCodeAt(0) === 42 /* STAR */) { + type = 2 /* Star */; + } + else { + type = 0 /* Static */; + } + flags = 2 << type; + if (flags & 12 /* Named */) { + part = part.slice(1); + names = names || []; + names.push(part); + shouldDecodes = shouldDecodes || []; + shouldDecodes.push((flags & 4 /* Decoded */) !== 0); + } + if (flags & 14 /* Counted */) { + types[type]++; + } + segments.push({ + type: type, + value: normalizeSegment(part) + }); + } + return { + names: names || EmptyArray, + shouldDecodes: shouldDecodes || EmptyArray, + }; +} +function isEqualCharSpec(spec, char, negate) { + return spec.char === char && spec.negate === negate; +} +// A State has a character specification and (`charSpec`) and a list of possible +// subsequent states (`nextStates`). +// +// If a State is an accepting state, it will also have several additional +// properties: +// +// * `regex`: A regular expression that is used to extract parameters from paths +// that reached this accepting state. +// * `handlers`: Information on how to convert the list of captures into calls +// to registered handlers with the specified parameters +// * `types`: How many static, dynamic or star segments in this route. Used to +// decide which route to use if multiple registered routes match a path. +// +// Currently, State is implemented naively by looping over `nextStates` and +// comparing a character specification against a character. A more efficient +// implementation would use a hash of keys pointing at one or more next states. +var State = function State(states, id, char, negate, repeat) { + this.states = states; + this.id = id; + this.char = char; + this.negate = negate; + this.nextStates = repeat ? id : null; + this.pattern = ""; + this._regex = undefined; + this.handlers = undefined; + this.types = undefined; +}; +State.prototype.regex = function regex$1 () { + if (!this._regex) { + this._regex = new RegExp(this.pattern); + } + return this._regex; +}; +State.prototype.get = function get (char, negate) { + var this$1 = this; + + var nextStates = this.nextStates; + if (nextStates === null) + { return; } + if (isArray(nextStates)) { + for (var i = 0; i < nextStates.length; i++) { + var child = this$1.states[nextStates[i]]; + if (isEqualCharSpec(child, char, negate)) { + return child; + } + } + } + else { + var child$1 = this.states[nextStates]; + if (isEqualCharSpec(child$1, char, negate)) { + return child$1; + } + } +}; +State.prototype.put = function put (char, negate, repeat) { + var state; + // If the character specification already exists in a child of the current + // state, just return that state. + if (state = this.get(char, negate)) { + return state; + } + // Make a new state for the character spec + var states = this.states; + state = new State(states, states.length, char, negate, repeat); + states[states.length] = state; + // Insert the new state as a child of the current state + if (this.nextStates == null) { + this.nextStates = state.id; + } + else if (isArray(this.nextStates)) { + this.nextStates.push(state.id); + } + else { + this.nextStates = [this.nextStates, state.id]; + } + // Return the new state + return state; +}; +// Find a list of child states matching the next character +State.prototype.match = function match (ch) { + var this$1 = this; + + var nextStates = this.nextStates; + if (!nextStates) + { return []; } + var returned = []; + if (isArray(nextStates)) { + for (var i = 0; i < nextStates.length; i++) { + var child = this$1.states[nextStates[i]]; + if (isMatch(child, ch)) { + returned.push(child); + } + } + } + else { + var child$1 = this.states[nextStates]; + if (isMatch(child$1, ch)) { + returned.push(child$1); + } + } + return returned; +}; +function isMatch(spec, char) { + return spec.negate ? spec.char !== char && spec.char !== -1 /* ANY */ : spec.char === char || spec.char === -1 /* ANY */; +} +// This is a somewhat naive strategy, but should work in a lot of cases +// A better strategy would properly resolve /posts/:id/new and /posts/edit/:id. +// +// This strategy generally prefers more static and less dynamic matching. +// Specifically, it +// +// * prefers fewer stars to more, then +// * prefers using stars for less of the match to more, then +// * prefers fewer dynamic segments to more, then +// * prefers more static segments to more +function sortSolutions(states) { + return states.sort(function (a, b) { + var ref = a.types || [0, 0, 0]; + var astatics = ref[0]; + var adynamics = ref[1]; + var astars = ref[2]; + var ref$1 = b.types || [0, 0, 0]; + var bstatics = ref$1[0]; + var bdynamics = ref$1[1]; + var bstars = ref$1[2]; + if (astars !== bstars) { + return astars - bstars; + } + if (astars) { + if (astatics !== bstatics) { + return bstatics - astatics; + } + if (adynamics !== bdynamics) { + return bdynamics - adynamics; + } + } + if (adynamics !== bdynamics) { + return adynamics - bdynamics; + } + if (astatics !== bstatics) { + return bstatics - astatics; + } + return 0; + }); +} +function recognizeChar(states, ch) { + var nextStates = []; + for (var i = 0, l = states.length; i < l; i++) { + var state = states[i]; + nextStates = nextStates.concat(state.match(ch)); + } + return nextStates; +} +var RecognizeResults = function RecognizeResults(queryParams) { + this.length = 0; + this.queryParams = queryParams || {}; +}; + +RecognizeResults.prototype.splice = Array.prototype.splice; +RecognizeResults.prototype.slice = Array.prototype.slice; +RecognizeResults.prototype.push = Array.prototype.push; +function findHandler(state, originalPath, queryParams) { + var handlers = state.handlers; + var regex = state.regex(); + if (!regex || !handlers) + { throw new Error("state not initialized"); } + var captures = originalPath.match(regex); + var currentCapture = 1; + var result = new RecognizeResults(queryParams); + result.length = handlers.length; + for (var i = 0; i < handlers.length; i++) { + var handler = handlers[i]; + var names = handler.names; + var shouldDecodes = handler.shouldDecodes; + var params = EmptyObject; + var isDynamic = false; + if (names !== EmptyArray && shouldDecodes !== EmptyArray) { + for (var j = 0; j < names.length; j++) { + isDynamic = true; + var name = names[j]; + var capture = captures && captures[currentCapture++]; + if (params === EmptyObject) { + params = {}; + } + if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS && shouldDecodes[j]) { + params[name] = capture && decodeURIComponent(capture); + } + else { + params[name] = capture; + } + } + } + result[i] = { + handler: handler.handler, + params: params, + isDynamic: isDynamic + }; + } + return result; +} +function decodeQueryParamPart(part) { + // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 + part = part.replace(/\+/gm, "%20"); + var result; + try { + result = decodeURIComponent(part); + } + catch (error) { + result = ""; + } + return result; +} +var RouteRecognizer = function RouteRecognizer() { + this.names = createMap(); + var states = []; + var state = new State(states, 0, -1 /* ANY */, true, false); + states[0] = state; + this.states = states; + this.rootState = state; +}; +RouteRecognizer.prototype.add = function add (routes, options) { + var currentState = this.rootState; + var pattern = "^"; + var types = [0, 0, 0]; + var handlers = new Array(routes.length); + var allSegments = []; + var isEmpty = true; + var j = 0; + for (var i = 0; i < routes.length; i++) { + var route = routes[i]; + var ref = parse(allSegments, route.path, types); + var names = ref.names; + var shouldDecodes = ref.shouldDecodes; + // preserve j so it points to the start of newly added segments + for (; j < allSegments.length; j++) { + var segment = allSegments[j]; + if (segment.type === 4 /* Epsilon */) { + continue; + } + isEmpty = false; + // Add a "/" for the new segment + currentState = currentState.put(47 /* SLASH */, false, false); + pattern += "/"; + // Add a representation of the segment to the NFA and regex + currentState = eachChar[segment.type](segment, currentState); + pattern += regex[segment.type](segment); + } + handlers[i] = { + handler: route.handler, + names: names, + shouldDecodes: shouldDecodes + }; + } + if (isEmpty) { + currentState = currentState.put(47 /* SLASH */, false, false); + pattern += "/"; + } + currentState.handlers = handlers; + currentState.pattern = pattern + "$"; + currentState.types = types; + var name; + if (typeof options === "object" && options !== null && options.as) { + name = options.as; + } + if (name) { + // if (this.names[name]) { + // throw new Error("You may not add a duplicate route named `" + name + "`."); + // } + this.names[name] = { + segments: allSegments, + handlers: handlers + }; + } +}; +RouteRecognizer.prototype.handlersFor = function handlersFor (name) { + var route = this.names[name]; + if (!route) { + throw new Error("There is no route named " + name); + } + var result = new Array(route.handlers.length); + for (var i = 0; i < route.handlers.length; i++) { + var handler = route.handlers[i]; + result[i] = handler; + } + return result; +}; +RouteRecognizer.prototype.hasRoute = function hasRoute (name) { + return !!this.names[name]; +}; +RouteRecognizer.prototype.generate = function generate$1 (name, params) { + var route = this.names[name]; + var output = ""; + if (!route) { + throw new Error("There is no route named " + name); + } + var segments = route.segments; + for (var i = 0; i < segments.length; i++) { + var segment = segments[i]; + if (segment.type === 4 /* Epsilon */) { + continue; + } + output += "/"; + output += generate[segment.type](segment, params); + } + if (output.charAt(0) !== "/") { + output = "/" + output; + } + if (params && params.queryParams) { + output += this.generateQueryString(params.queryParams); + } + return output; +}; +RouteRecognizer.prototype.generateQueryString = function generateQueryString (params) { + var pairs = []; + var keys = Object.keys(params); + keys.sort(); + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = params[key]; + if (value == null) { + continue; + } + var pair = encodeURIComponent(key); + if (isArray(value)) { + for (var j = 0; j < value.length; j++) { + var arrayPair = key + "[]" + "=" + encodeURIComponent(value[j]); + pairs.push(arrayPair); + } + } + else { + pair += "=" + encodeURIComponent(value); + pairs.push(pair); + } + } + if (pairs.length === 0) { + return ""; + } + return "?" + pairs.join("&"); +}; +RouteRecognizer.prototype.parseQueryString = function parseQueryString (queryString) { + var pairs = queryString.split("&"); + var queryParams = {}; + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split("="), key = decodeQueryParamPart(pair[0]), keyLength = key.length, isArray = false, value = (void 0); + if (pair.length === 1) { + value = "true"; + } + else { + // Handle arrays + if (keyLength > 2 && key.slice(keyLength - 2) === "[]") { + isArray = true; + key = key.slice(0, keyLength - 2); + if (!queryParams[key]) { + queryParams[key] = []; + } + } + value = pair[1] ? decodeQueryParamPart(pair[1]) : ""; + } + if (isArray) { + queryParams[key].push(value); + } + else { + queryParams[key] = value; + } + } + return queryParams; +}; +RouteRecognizer.prototype.recognize = function recognize (path) { + var results; + var states = [this.rootState]; + var queryParams = {}; + var isSlashDropped = false; + var hashStart = path.indexOf("#"); + if (hashStart !== -1) { + path = path.substr(0, hashStart); + } + var queryStart = path.indexOf("?"); + if (queryStart !== -1) { + var queryString = path.substr(queryStart + 1, path.length); + path = path.substr(0, queryStart); + queryParams = this.parseQueryString(queryString); + } + if (path.charAt(0) !== "/") { + path = "/" + path; + } + var originalPath = path; + if (RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS) { + path = normalizePath(path); + } + else { + path = decodeURI(path); + originalPath = decodeURI(originalPath); + } + var pathLen = path.length; + if (pathLen > 1 && path.charAt(pathLen - 1) === "/") { + path = path.substr(0, pathLen - 1); + originalPath = originalPath.substr(0, originalPath.length - 1); + isSlashDropped = true; + } + for (var i = 0; i < path.length; i++) { + states = recognizeChar(states, path.charCodeAt(i)); + if (!states.length) { + break; + } + } + var solutions = []; + for (var i$1 = 0; i$1 < states.length; i$1++) { + if (states[i$1].handlers) { + solutions.push(states[i$1]); + } + } + states = sortSolutions(solutions); + var state = solutions[0]; + if (state && state.handlers) { + // if a trailing slash was dropped and a star segment is the last segment + // specified, put the trailing slash back + if (isSlashDropped && state.pattern && state.pattern.slice(-5) === "(.+)$") { + originalPath = originalPath + "/"; + } + results = findHandler(state, originalPath, queryParams); + } + return results; +}; +RouteRecognizer.VERSION = "0.3.4"; +// Set to false to opt-out of encoding and decoding path segments. +// See https://github.com/tildeio/route-recognizer/pull/55 +RouteRecognizer.ENCODE_AND_DECODE_PATH_SEGMENTS = true; +RouteRecognizer.Normalizer = { + normalizeSegment: normalizeSegment, normalizePath: normalizePath, encodePathSegment: encodePathSegment +}; +RouteRecognizer.prototype.map = map; + +export default RouteRecognizer; + +//# sourceMappingURL=route-recognizer.es.js.map diff --git a/ember-vendored-pr-19806/dependencies/router_js.js b/ember-vendored-pr-19806/dependencies/router_js.js new file mode 100644 index 0000000..11b6037 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/router_js.js @@ -0,0 +1,1963 @@ +import { Promise } from 'rsvp'; +import { DEBUG } from '@glimmer/env'; +import RouteRecognizer from 'route-recognizer'; + +function buildTransitionAborted() { + let error = new Error('TransitionAborted'); + error.name = 'TransitionAborted'; + error.code = 'TRANSITION_ABORTED'; + return error; +} +function isTransitionAborted(maybeError) { + return (typeof maybeError === 'object' && + maybeError !== null && + maybeError.code === 'TRANSITION_ABORTED'); +} +function isAbortable(maybeAbortable) { + return (typeof maybeAbortable === 'object' && + maybeAbortable !== null && + typeof maybeAbortable.isAborted === 'boolean'); +} +function throwIfAborted(maybe) { + if (isAbortable(maybe) && maybe.isAborted) { + throw buildTransitionAborted(); + } +} + +const slice = Array.prototype.slice; +const hasOwnProperty = Object.prototype.hasOwnProperty; +/** + Determines if an object is Promise by checking if it is "thenable". +**/ +function isPromise(p) { + return p !== null && typeof p === 'object' && typeof p.then === 'function'; +} +function merge(hash, other) { + for (let prop in other) { + if (hasOwnProperty.call(other, prop)) { + hash[prop] = other[prop]; + } + } +} +/** + @private + + Extracts query params from the end of an array +**/ +function extractQueryParams(array) { + let len = array && array.length, head, queryParams; + if (len && len > 0) { + let obj = array[len - 1]; + if (isQueryParams(obj)) { + queryParams = obj.queryParams; + head = slice.call(array, 0, len - 1); + return [head, queryParams]; + } + } + return [array, null]; +} +function isQueryParams(obj) { + return obj && hasOwnProperty.call(obj, 'queryParams'); +} +/** + @private + + Coerces query param properties and array elements into strings. +**/ +function coerceQueryParamsToString(queryParams) { + for (let key in queryParams) { + let val = queryParams[key]; + if (typeof val === 'number') { + queryParams[key] = '' + val; + } + else if (Array.isArray(val)) { + for (let i = 0, l = val.length; i < l; i++) { + val[i] = '' + val[i]; + } + } + } +} +/** + @private + */ +function log(router, ...args) { + if (!router.log) { + return; + } + if (args.length === 2) { + let [sequence, msg] = args; + router.log('Transition #' + sequence + ': ' + msg); + } + else { + let [msg] = args; + router.log(msg); + } +} +function isParam(object) { + return (typeof object === 'string' || + object instanceof String || + typeof object === 'number' || + object instanceof Number); +} +function forEach(array, callback) { + for (let i = 0, l = array.length; i < l && callback(array[i]) !== false; i++) { + // empty intentionally + } +} +function getChangelist(oldObject, newObject) { + let key; + let results = { + all: {}, + changed: {}, + removed: {}, + }; + merge(results.all, newObject); + let didChange = false; + coerceQueryParamsToString(oldObject); + coerceQueryParamsToString(newObject); + // Calculate removals + for (key in oldObject) { + if (hasOwnProperty.call(oldObject, key)) { + if (!hasOwnProperty.call(newObject, key)) { + didChange = true; + results.removed[key] = oldObject[key]; + } + } + } + // Calculate changes + for (key in newObject) { + if (hasOwnProperty.call(newObject, key)) { + let oldElement = oldObject[key]; + let newElement = newObject[key]; + if (isArray(oldElement) && isArray(newElement)) { + if (oldElement.length !== newElement.length) { + results.changed[key] = newObject[key]; + didChange = true; + } + else { + for (let i = 0, l = oldElement.length; i < l; i++) { + if (oldElement[i] !== newElement[i]) { + results.changed[key] = newObject[key]; + didChange = true; + } + } + } + } + else if (oldObject[key] !== newObject[key]) { + results.changed[key] = newObject[key]; + didChange = true; + } + } + } + return didChange ? results : undefined; +} +function isArray(obj) { + return Array.isArray(obj); +} +function promiseLabel(label) { + return 'Router: ' + label; +} + +const STATE_SYMBOL = `__STATE__-2619860001345920-3322w3`; +const PARAMS_SYMBOL = `__PARAMS__-261986232992830203-23323`; +const QUERY_PARAMS_SYMBOL = `__QPS__-2619863929824844-32323`; +/** + A Transition is a thenable (a promise-like object) that represents + an attempt to transition to another route. It can be aborted, either + explicitly via `abort` or by attempting another transition while a + previous one is still underway. An aborted transition can also + be `retry()`d later. + + @class Transition + @constructor + @param {Object} router + @param {Object} intent + @param {Object} state + @param {Object} error + @private + */ +class Transition { + constructor(router, intent, state, error = undefined, previousTransition = undefined) { + this.from = null; + this.to = undefined; + this.isAborted = false; + this.isActive = true; + this.urlMethod = 'update'; + this.resolveIndex = 0; + this.queryParamsOnly = false; + this.isTransition = true; + this.isCausedByAbortingTransition = false; + this.isCausedByInitialTransition = false; + this.isCausedByAbortingReplaceTransition = false; + this._visibleQueryParams = {}; + this.isIntermediate = false; + this[STATE_SYMBOL] = state || router.state; + this.intent = intent; + this.router = router; + this.data = (intent && intent.data) || {}; + this.resolvedModels = {}; + this[QUERY_PARAMS_SYMBOL] = {}; + this.promise = undefined; + this.error = undefined; + this[PARAMS_SYMBOL] = {}; + this.routeInfos = []; + this.targetName = undefined; + this.pivotHandler = undefined; + this.sequence = -1; + if (DEBUG) { + let error = new Error(`Transition creation stack`); + this.debugCreationStack = () => error.stack; + // not aborted yet, will be replaced when `this.isAborted` is set + this.debugAbortStack = () => undefined; + this.debugPreviousTransition = previousTransition; + } + if (error) { + this.promise = Promise.reject(error); + this.error = error; + return; + } + // if you're doing multiple redirects, need the new transition to know if it + // is actually part of the first transition or not. Any further redirects + // in the initial transition also need to know if they are part of the + // initial transition + this.isCausedByAbortingTransition = !!previousTransition; + this.isCausedByInitialTransition = + !!previousTransition && + (previousTransition.isCausedByInitialTransition || previousTransition.sequence === 0); + // Every transition in the chain is a replace + this.isCausedByAbortingReplaceTransition = + !!previousTransition && + previousTransition.urlMethod === 'replace' && + (!previousTransition.isCausedByAbortingTransition || + previousTransition.isCausedByAbortingReplaceTransition); + if (state) { + this[PARAMS_SYMBOL] = state.params; + this[QUERY_PARAMS_SYMBOL] = state.queryParams; + this.routeInfos = state.routeInfos; + let len = state.routeInfos.length; + if (len) { + this.targetName = state.routeInfos[len - 1].name; + } + for (let i = 0; i < len; ++i) { + let handlerInfo = state.routeInfos[i]; + // TODO: this all seems hacky + if (!handlerInfo.isResolved) { + break; + } + this.pivotHandler = handlerInfo.route; + } + this.sequence = router.currentSequence++; + this.promise = state.resolve(this).catch((result) => { + let error = this.router.transitionDidError(result, this); + throw error; + }, promiseLabel('Handle Abort')); + } + else { + this.promise = Promise.resolve(this[STATE_SYMBOL]); + this[PARAMS_SYMBOL] = {}; + } + } + /** + The Transition's internal promise. Calling `.then` on this property + is that same as calling `.then` on the Transition object itself, but + this property is exposed for when you want to pass around a + Transition's promise, but not the Transition object itself, since + Transition object can be externally `abort`ed, while the promise + cannot. + + @property promise + @type {Object} + @public + */ + /** + Custom state can be stored on a Transition's `data` object. + This can be useful for decorating a Transition within an earlier + hook and shared with a later hook. Properties set on `data` will + be copied to new transitions generated by calling `retry` on this + transition. + + @property data + @type {Object} + @public + */ + /** + A standard promise hook that resolves if the transition + succeeds and rejects if it fails/redirects/aborts. + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thenable, + but not the Transition itself. + + @method then + @param {Function} onFulfilled + @param {Function} onRejected + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + then(onFulfilled, onRejected, label) { + return this.promise.then(onFulfilled, onRejected, label); + } + /** + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thennable, + but not the Transition itself. + + @method catch + @param {Function} onRejection + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + catch(onRejection, label) { + return this.promise.catch(onRejection, label); + } + /** + + Forwards to the internal `promise` property which you can + use in situations where you want to pass around a thenable, + but not the Transition itself. + + @method finally + @param {Function} callback + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + @public + */ + finally(callback, label) { + return this.promise.finally(callback, label); + } + /** + Aborts the Transition. Note you can also implicitly abort a transition + by initiating another transition while a previous one is underway. + + @method abort + @return {Transition} this transition + @public + */ + abort() { + this.rollback(); + let transition = new Transition(this.router, undefined, undefined, undefined); + transition.to = this.from; + transition.from = this.from; + transition.isAborted = true; + this.router.routeWillChange(transition); + this.router.routeDidChange(transition); + return this; + } + rollback() { + if (!this.isAborted) { + log(this.router, this.sequence, this.targetName + ': transition was aborted'); + if (DEBUG) { + let error = new Error(`Transition aborted stack`); + this.debugAbortStack = () => error.stack; + } + if (this.intent !== undefined && this.intent !== null) { + this.intent.preTransitionState = this.router.state; + } + this.isAborted = true; + this.isActive = false; + this.router.activeTransition = undefined; + } + } + redirect(newTransition) { + this.rollback(); + this.router.routeWillChange(newTransition); + } + /** + + Retries a previously-aborted transition (making sure to abort the + transition if it's still active). Returns a new transition that + represents the new attempt to transition. + + @method retry + @return {Transition} new transition + @public + */ + retry() { + // TODO: add tests for merged state retry()s + this.abort(); + let newTransition = this.router.transitionByIntent(this.intent, false); + // inheriting a `null` urlMethod is not valid + // the urlMethod is only set to `null` when + // the transition is initiated *after* the url + // has been updated (i.e. `router.handleURL`) + // + // in that scenario, the url method cannot be + // inherited for a new transition because then + // the url would not update even though it should + if (this.urlMethod !== null) { + newTransition.method(this.urlMethod); + } + return newTransition; + } + /** + + Sets the URL-changing method to be employed at the end of a + successful transition. By default, a new Transition will just + use `updateURL`, but passing 'replace' to this method will + cause the URL to update using 'replaceWith' instead. Omitting + a parameter will disable the URL change, allowing for transitions + that don't update the URL at completion (this is also used for + handleURL, since the URL has already changed before the + transition took place). + + @method method + @param {String} method the type of URL-changing method to use + at the end of a transition. Accepted values are 'replace', + falsy values, or any other non-falsy value (which is + interpreted as an updateURL transition). + + @return {Transition} this transition + @public + */ + method(method) { + this.urlMethod = method; + return this; + } + // Alias 'trigger' as 'send' + send(ignoreFailure = false, _name, err, transition, handler) { + this.trigger(ignoreFailure, _name, err, transition, handler); + } + /** + + Fires an event on the current list of resolved/resolving + handlers within this transition. Useful for firing events + on route hierarchies that haven't fully been entered yet. + + Note: This method is also aliased as `send` + + @method trigger + @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error + @param {String} name the name of the event to fire + @public + */ + trigger(ignoreFailure = false, name, ...args) { + // TODO: Deprecate the current signature + if (typeof ignoreFailure === 'string') { + name = ignoreFailure; + ignoreFailure = false; + } + this.router.triggerEvent(this[STATE_SYMBOL].routeInfos.slice(0, this.resolveIndex + 1), ignoreFailure, name, args); + } + /** + Transitions are aborted and their promises rejected + when redirects occur; this method returns a promise + that will follow any redirects that occur and fulfill + with the value fulfilled by any redirecting transitions + that occur. + + @method followRedirects + @return {Promise} a promise that fulfills with the same + value that the final redirecting transition fulfills with + @public + */ + followRedirects() { + let router = this.router; + return this.promise.catch(function (reason) { + if (router.activeTransition) { + return router.activeTransition.followRedirects(); + } + return Promise.reject(reason); + }); + } + toString() { + return 'Transition (sequence ' + this.sequence + ')'; + } + /** + @private + */ + log(message) { + log(this.router, this.sequence, message); + } +} +/** + @private + + Logs and returns an instance of TransitionAborted. + */ +function logAbort(transition) { + log(transition.router, transition.sequence, 'detected abort.'); + return buildTransitionAborted(); +} +function isTransition(obj) { + return typeof obj === 'object' && obj instanceof Transition && obj.isTransition; +} +function prepareResult(obj) { + if (isTransition(obj)) { + return null; + } + return obj; +} + +let ROUTE_INFOS = new WeakMap(); +function toReadOnlyRouteInfo(routeInfos, queryParams = {}, includeAttributes = false) { + return routeInfos.map((info, i) => { + let { name, params, paramNames, context, route } = info; + if (ROUTE_INFOS.has(info) && includeAttributes) { + let routeInfo = ROUTE_INFOS.get(info); + routeInfo = attachMetadata(route, routeInfo); + let routeInfoWithAttribute = createRouteInfoWithAttributes(routeInfo, context); + ROUTE_INFOS.set(info, routeInfoWithAttribute); + return routeInfoWithAttribute; + } + let routeInfo = { + find(predicate, thisArg) { + let publicInfo; + let arr = []; + if (predicate.length === 3) { + arr = routeInfos.map((info) => ROUTE_INFOS.get(info)); + } + for (let i = 0; routeInfos.length > i; i++) { + publicInfo = ROUTE_INFOS.get(routeInfos[i]); + if (predicate.call(thisArg, publicInfo, i, arr)) { + return publicInfo; + } + } + return undefined; + }, + get name() { + return name; + }, + get paramNames() { + return paramNames; + }, + get metadata() { + return buildRouteInfoMetadata(info.route); + }, + get parent() { + let parent = routeInfos[i - 1]; + if (parent === undefined) { + return null; + } + return ROUTE_INFOS.get(parent); + }, + get child() { + let child = routeInfos[i + 1]; + if (child === undefined) { + return null; + } + return ROUTE_INFOS.get(child); + }, + get localName() { + let parts = this.name.split('.'); + return parts[parts.length - 1]; + }, + get params() { + return params; + }, + get queryParams() { + return queryParams; + }, + }; + if (includeAttributes) { + routeInfo = createRouteInfoWithAttributes(routeInfo, context); + } + ROUTE_INFOS.set(info, routeInfo); + return routeInfo; + }); +} +function createRouteInfoWithAttributes(routeInfo, context) { + let attributes = { + get attributes() { + return context; + }, + }; + if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('attributes')) { + return Object.freeze(Object.assign({}, routeInfo, attributes)); + } + return Object.assign(routeInfo, attributes); +} +function buildRouteInfoMetadata(route) { + if (route !== undefined && route !== null && route.buildRouteInfoMetadata !== undefined) { + return route.buildRouteInfoMetadata(); + } + return null; +} +function attachMetadata(route, routeInfo) { + let metadata = { + get metadata() { + return buildRouteInfoMetadata(route); + }, + }; + if (!Object.isExtensible(routeInfo) || routeInfo.hasOwnProperty('metadata')) { + return Object.freeze(Object.assign({}, routeInfo, metadata)); + } + return Object.assign(routeInfo, metadata); +} +class InternalRouteInfo { + constructor(router, name, paramNames, route) { + this._routePromise = undefined; + this._route = null; + this.params = {}; + this.isResolved = false; + this.name = name; + this.paramNames = paramNames; + this.router = router; + if (route) { + this._processRoute(route); + } + } + getModel(_transition) { + return Promise.resolve(this.context); + } + serialize(_context) { + return this.params || {}; + } + resolve(transition) { + return Promise.resolve(this.routePromise) + .then((route) => { + throwIfAborted(transition); + return route; + }) + .then(() => this.runBeforeModelHook(transition)) + .then(() => throwIfAborted(transition)) + .then(() => this.getModel(transition)) + .then((resolvedModel) => { + throwIfAborted(transition); + return resolvedModel; + }) + .then((resolvedModel) => this.runAfterModelHook(transition, resolvedModel)) + .then((resolvedModel) => this.becomeResolved(transition, resolvedModel)); + } + becomeResolved(transition, resolvedContext) { + let params = this.serialize(resolvedContext); + if (transition) { + this.stashResolvedModel(transition, resolvedContext); + transition[PARAMS_SYMBOL] = transition[PARAMS_SYMBOL] || {}; + transition[PARAMS_SYMBOL][this.name] = params; + } + let context; + let contextsMatch = resolvedContext === this.context; + if ('context' in this || !contextsMatch) { + context = resolvedContext; + } + let cached = ROUTE_INFOS.get(this); + let resolved = new ResolvedRouteInfo(this.router, this.name, this.paramNames, params, this.route, context); + if (cached !== undefined) { + ROUTE_INFOS.set(resolved, cached); + } + return resolved; + } + shouldSupersede(routeInfo) { + // Prefer this newer routeInfo over `other` if: + // 1) The other one doesn't exist + // 2) The names don't match + // 3) This route has a context that doesn't match + // the other one (or the other one doesn't have one). + // 4) This route has parameters that don't match the other. + if (!routeInfo) { + return true; + } + let contextsMatch = routeInfo.context === this.context; + return (routeInfo.name !== this.name || + ('context' in this && !contextsMatch) || + (this.hasOwnProperty('params') && !paramsMatch(this.params, routeInfo.params))); + } + get route() { + // _route could be set to either a route object or undefined, so we + // compare against null to know when it's been set + if (this._route !== null) { + return this._route; + } + return this.fetchRoute(); + } + set route(route) { + this._route = route; + } + get routePromise() { + if (this._routePromise) { + return this._routePromise; + } + this.fetchRoute(); + return this._routePromise; + } + set routePromise(routePromise) { + this._routePromise = routePromise; + } + log(transition, message) { + if (transition.log) { + transition.log(this.name + ': ' + message); + } + } + updateRoute(route) { + route._internalName = this.name; + return (this.route = route); + } + runBeforeModelHook(transition) { + if (transition.trigger) { + transition.trigger(true, 'willResolveModel', transition, this.route); + } + let result; + if (this.route) { + if (this.route.beforeModel !== undefined) { + result = this.route.beforeModel(transition); + } + } + if (isTransition(result)) { + result = null; + } + return Promise.resolve(result); + } + runAfterModelHook(transition, resolvedModel) { + // Stash the resolved model on the payload. + // This makes it possible for users to swap out + // the resolved model in afterModel. + let name = this.name; + this.stashResolvedModel(transition, resolvedModel); + let result; + if (this.route !== undefined) { + if (this.route.afterModel !== undefined) { + result = this.route.afterModel(resolvedModel, transition); + } + } + result = prepareResult(result); + return Promise.resolve(result).then(() => { + // Ignore the fulfilled value returned from afterModel. + // Return the value stashed in resolvedModels, which + // might have been swapped out in afterModel. + return transition.resolvedModels[name]; + }); + } + stashResolvedModel(transition, resolvedModel) { + transition.resolvedModels = transition.resolvedModels || {}; + transition.resolvedModels[this.name] = resolvedModel; + } + fetchRoute() { + let route = this.router.getRoute(this.name); + return this._processRoute(route); + } + _processRoute(route) { + // Setup a routePromise so that we can wait for asynchronously loaded routes + this.routePromise = Promise.resolve(route); + // Wait until the 'route' property has been updated when chaining to a route + // that is a promise + if (isPromise(route)) { + this.routePromise = this.routePromise.then((r) => { + return this.updateRoute(r); + }); + // set to undefined to avoid recursive loop in the route getter + return (this.route = undefined); + } + else if (route) { + return this.updateRoute(route); + } + return undefined; + } +} +class ResolvedRouteInfo extends InternalRouteInfo { + constructor(router, name, paramNames, params, route, context) { + super(router, name, paramNames, route); + this.params = params; + this.isResolved = true; + this.context = context; + } + resolve(transition) { + // A ResolvedRouteInfo just resolved with itself. + if (transition && transition.resolvedModels) { + transition.resolvedModels[this.name] = this.context; + } + return Promise.resolve(this); + } +} +class UnresolvedRouteInfoByParam extends InternalRouteInfo { + constructor(router, name, paramNames, params, route) { + super(router, name, paramNames, route); + this.params = {}; + this.params = params; + } + getModel(transition) { + let fullParams = this.params; + if (transition && transition[QUERY_PARAMS_SYMBOL]) { + fullParams = {}; + merge(fullParams, this.params); + fullParams.queryParams = transition[QUERY_PARAMS_SYMBOL]; + } + let route = this.route; + let result; + if (route.deserialize) { + result = route.deserialize(fullParams, transition); + } + else if (route.model) { + result = route.model(fullParams, transition); + } + if (result && isTransition(result)) { + result = undefined; + } + return Promise.resolve(result); + } +} +class UnresolvedRouteInfoByObject extends InternalRouteInfo { + constructor(router, name, paramNames, context) { + super(router, name, paramNames); + this.context = context; + this.serializer = this.router.getSerializer(name); + } + getModel(transition) { + if (this.router.log !== undefined) { + this.router.log(this.name + ': resolving provided model'); + } + return super.getModel(transition); + } + /** + @private + + Serializes a route using its custom `serialize` method or + by a default that looks up the expected property name from + the dynamic segment. + + @param {Object} model the model to be serialized for this route + */ + serialize(model) { + let { paramNames, context } = this; + if (!model) { + model = context; + } + let object = {}; + if (isParam(model)) { + object[paramNames[0]] = model; + return object; + } + // Use custom serialize if it exists. + if (this.serializer) { + // invoke this.serializer unbound (getSerializer returns a stateless function) + return this.serializer.call(null, model, paramNames); + } + else if (this.route !== undefined) { + if (this.route.serialize) { + return this.route.serialize(model, paramNames); + } + } + if (paramNames.length !== 1) { + return; + } + let name = paramNames[0]; + if (/_id$/.test(name)) { + object[name] = model.id; + } + else { + object[name] = model; + } + return object; + } +} +function paramsMatch(a, b) { + if (!a !== !b) { + // Only one is null. + return false; + } + if (!a) { + // Both must be null. + return true; + } + // Note: this assumes that both params have the same + // number of keys, but since we're comparing the + // same routes, they should. + for (let k in a) { + if (a.hasOwnProperty(k) && a[k] !== b[k]) { + return false; + } + } + return true; +} + +class TransitionIntent { + constructor(router, data = {}) { + this.router = router; + this.data = data; + } +} + +function handleError(currentState, transition, error) { + // This is the only possible + // reject value of TransitionState#resolve + let routeInfos = currentState.routeInfos; + let errorHandlerIndex = transition.resolveIndex >= routeInfos.length ? routeInfos.length - 1 : transition.resolveIndex; + let wasAborted = transition.isAborted; + throw new TransitionError(error, currentState.routeInfos[errorHandlerIndex].route, wasAborted, currentState); +} +function resolveOneRouteInfo(currentState, transition) { + if (transition.resolveIndex === currentState.routeInfos.length) { + // This is is the only possible + // fulfill value of TransitionState#resolve + return; + } + let routeInfo = currentState.routeInfos[transition.resolveIndex]; + return routeInfo + .resolve(transition) + .then(proceed.bind(null, currentState, transition), null, currentState.promiseLabel('Proceed')); +} +function proceed(currentState, transition, resolvedRouteInfo) { + let wasAlreadyResolved = currentState.routeInfos[transition.resolveIndex].isResolved; + // Swap the previously unresolved routeInfo with + // the resolved routeInfo + currentState.routeInfos[transition.resolveIndex++] = resolvedRouteInfo; + if (!wasAlreadyResolved) { + // Call the redirect hook. The reason we call it here + // vs. afterModel is so that redirects into child + // routes don't re-run the model hooks for this + // already-resolved route. + let { route } = resolvedRouteInfo; + if (route !== undefined) { + if (route.redirect) { + route.redirect(resolvedRouteInfo.context, transition); + } + } + } + // Proceed after ensuring that the redirect hook + // didn't abort this transition by transitioning elsewhere. + throwIfAborted(transition); + return resolveOneRouteInfo(currentState, transition); +} +class TransitionState { + constructor() { + this.routeInfos = []; + this.queryParams = {}; + this.params = {}; + } + promiseLabel(label) { + let targetName = ''; + forEach(this.routeInfos, function (routeInfo) { + if (targetName !== '') { + targetName += '.'; + } + targetName += routeInfo.name; + return true; + }); + return promiseLabel("'" + targetName + "': " + label); + } + resolve(transition) { + // First, calculate params for this state. This is useful + // information to provide to the various route hooks. + let params = this.params; + forEach(this.routeInfos, (routeInfo) => { + params[routeInfo.name] = routeInfo.params || {}; + return true; + }); + transition.resolveIndex = 0; + // The prelude RSVP.resolve() async moves us into the promise land. + return Promise.resolve(null, this.promiseLabel('Start transition')) + .then(resolveOneRouteInfo.bind(null, this, transition), null, this.promiseLabel('Resolve route')) + .catch(handleError.bind(null, this, transition), this.promiseLabel('Handle error')) + .then(() => this); + } +} +class TransitionError { + constructor(error, route, wasAborted, state) { + this.error = error; + this.route = route; + this.wasAborted = wasAborted; + this.state = state; + } +} + +class NamedTransitionIntent extends TransitionIntent { + constructor(router, name, pivotHandler, contexts = [], queryParams = {}, data) { + super(router, data); + this.preTransitionState = undefined; + this.name = name; + this.pivotHandler = pivotHandler; + this.contexts = contexts; + this.queryParams = queryParams; + } + applyToState(oldState, isIntermediate) { + // TODO: WTF fix me + let partitionedArgs = extractQueryParams([this.name].concat(this.contexts)), pureArgs = partitionedArgs[0], handlers = this.router.recognizer.handlersFor(pureArgs[0]); + let targetRouteName = handlers[handlers.length - 1].handler; + return this.applyToHandlers(oldState, handlers, targetRouteName, isIntermediate, false); + } + applyToHandlers(oldState, parsedHandlers, targetRouteName, isIntermediate, checkingIfActive) { + let i, len; + let newState = new TransitionState(); + let objects = this.contexts.slice(0); + let invalidateIndex = parsedHandlers.length; + // Pivot handlers are provided for refresh transitions + if (this.pivotHandler) { + for (i = 0, len = parsedHandlers.length; i < len; ++i) { + if (parsedHandlers[i].handler === this.pivotHandler._internalName) { + invalidateIndex = i; + break; + } + } + } + for (i = parsedHandlers.length - 1; i >= 0; --i) { + let result = parsedHandlers[i]; + let name = result.handler; + let oldHandlerInfo = oldState.routeInfos[i]; + let newHandlerInfo = null; + if (result.names.length > 0) { + if (i >= invalidateIndex) { + newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); + } + else { + newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, result.names, objects, oldHandlerInfo, targetRouteName, i); + } + } + else { + // This route has no dynamic segment. + // Therefore treat as a param-based handlerInfo + // with empty params. This will cause the `model` + // hook to be called with empty params, which is desirable. + newHandlerInfo = this.createParamHandlerInfo(name, result.names, objects, oldHandlerInfo); + } + if (checkingIfActive) { + // If we're performing an isActive check, we want to + // serialize URL params with the provided context, but + // ignore mismatches between old and new context. + newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context); + let oldContext = oldHandlerInfo && oldHandlerInfo.context; + if (result.names.length > 0 && + oldHandlerInfo.context !== undefined && + newHandlerInfo.context === oldContext) { + // If contexts match in isActive test, assume params also match. + // This allows for flexibility in not requiring that every last + // handler provide a `serialize` method + newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; + } + newHandlerInfo.context = oldContext; + } + let handlerToUse = oldHandlerInfo; + if (i >= invalidateIndex || newHandlerInfo.shouldSupersede(oldHandlerInfo)) { + invalidateIndex = Math.min(i, invalidateIndex); + handlerToUse = newHandlerInfo; + } + if (isIntermediate && !checkingIfActive) { + handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context); + } + newState.routeInfos.unshift(handlerToUse); + } + if (objects.length > 0) { + throw new Error('More context objects were passed than there are dynamic segments for the route: ' + + targetRouteName); + } + if (!isIntermediate) { + this.invalidateChildren(newState.routeInfos, invalidateIndex); + } + merge(newState.queryParams, this.queryParams || {}); + if (isIntermediate && oldState.queryParams) { + merge(newState.queryParams, oldState.queryParams); + } + return newState; + } + invalidateChildren(handlerInfos, invalidateIndex) { + for (let i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { + let handlerInfo = handlerInfos[i]; + if (handlerInfo.isResolved) { + let { name, params, route, paramNames } = handlerInfos[i]; + handlerInfos[i] = new UnresolvedRouteInfoByParam(this.router, name, paramNames, params, route); + } + } + } + getHandlerInfoForDynamicSegment(name, names, objects, oldHandlerInfo, _targetRouteName, i) { + let objectToUse; + if (objects.length > 0) { + // Use the objects provided for this transition. + objectToUse = objects[objects.length - 1]; + if (isParam(objectToUse)) { + return this.createParamHandlerInfo(name, names, objects, oldHandlerInfo); + } + else { + objects.pop(); + } + } + else if (oldHandlerInfo && oldHandlerInfo.name === name) { + // Reuse the matching oldHandlerInfo + return oldHandlerInfo; + } + else { + if (this.preTransitionState) { + let preTransitionHandlerInfo = this.preTransitionState.routeInfos[i]; + objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context; + } + else { + // Ideally we should throw this error to provide maximal + // information to the user that not enough context objects + // were provided, but this proves too cumbersome in Ember + // in cases where inner template helpers are evaluated + // before parent helpers un-render, in which cases this + // error somewhat prematurely fires. + //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); + return oldHandlerInfo; + } + } + return new UnresolvedRouteInfoByObject(this.router, name, names, objectToUse); + } + createParamHandlerInfo(name, names, objects, oldHandlerInfo) { + let params = {}; + // Soak up all the provided string/numbers + let numNames = names.length; + let missingParams = []; + while (numNames--) { + // Only use old params if the names match with the new handler + let oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {}; + let peek = objects[objects.length - 1]; + let paramName = names[numNames]; + if (isParam(peek)) { + params[paramName] = '' + objects.pop(); + } + else { + // If we're here, this means only some of the params + // were string/number params, so try and use a param + // value from a previous handler. + if (oldParams.hasOwnProperty(paramName)) { + params[paramName] = oldParams[paramName]; + } + else { + missingParams.push(paramName); + } + } + } + if (missingParams.length > 0) { + throw new Error(`You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route ${name}.` + + ` Missing params: ${missingParams}`); + } + return new UnresolvedRouteInfoByParam(this.router, name, names, params); + } +} + +const UnrecognizedURLError = (function () { + UnrecognizedURLError.prototype = Object.create(Error.prototype); + UnrecognizedURLError.prototype.constructor = UnrecognizedURLError; + function UnrecognizedURLError(message) { + let error = Error.call(this, message); + this.name = 'UnrecognizedURLError'; + this.message = message || 'UnrecognizedURL'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, UnrecognizedURLError); + } + else { + this.stack = error.stack; + } + } + return UnrecognizedURLError; +})(); + +class URLTransitionIntent extends TransitionIntent { + constructor(router, url, data) { + super(router, data); + this.url = url; + this.preTransitionState = undefined; + } + applyToState(oldState) { + let newState = new TransitionState(); + let results = this.router.recognizer.recognize(this.url), i, len; + if (!results) { + throw new UnrecognizedURLError(this.url); + } + let statesDiffer = false; + let _url = this.url; + // Checks if a handler is accessible by URL. If it is not, an error is thrown. + // For the case where the handler is loaded asynchronously, the error will be + // thrown once it is loaded. + function checkHandlerAccessibility(handler) { + if (handler && handler.inaccessibleByURL) { + throw new UnrecognizedURLError(_url); + } + return handler; + } + for (i = 0, len = results.length; i < len; ++i) { + let result = results[i]; + let name = result.handler; + let paramNames = []; + if (this.router.recognizer.hasRoute(name)) { + paramNames = this.router.recognizer.handlersFor(name)[i].names; + } + let newRouteInfo = new UnresolvedRouteInfoByParam(this.router, name, paramNames, result.params); + let route = newRouteInfo.route; + if (route) { + checkHandlerAccessibility(route); + } + else { + // If the handler is being loaded asynchronously, check if we can + // access it after it has resolved + newRouteInfo.routePromise = newRouteInfo.routePromise.then(checkHandlerAccessibility); + } + let oldRouteInfo = oldState.routeInfos[i]; + if (statesDiffer || newRouteInfo.shouldSupersede(oldRouteInfo)) { + statesDiffer = true; + newState.routeInfos[i] = newRouteInfo; + } + else { + newState.routeInfos[i] = oldRouteInfo; + } + } + merge(newState.queryParams, results.queryParams); + return newState; + } +} + +class Router { + constructor(logger) { + this._lastQueryParams = {}; + this.state = undefined; + this.oldState = undefined; + this.activeTransition = undefined; + this.currentRouteInfos = undefined; + this._changedQueryParams = undefined; + this.currentSequence = 0; + this.log = logger; + this.recognizer = new RouteRecognizer(); + this.reset(); + } + /** + The main entry point into the router. The API is essentially + the same as the `map` method in `route-recognizer`. + + This method extracts the String handler at the last `.to()` + call and uses it as the name of the whole route. + + @param {Function} callback + */ + map(callback) { + this.recognizer.map(callback, function (recognizer, routes) { + for (let i = routes.length - 1, proceed = true; i >= 0 && proceed; --i) { + let route = routes[i]; + let handler = route.handler; + recognizer.add(routes, { as: handler }); + proceed = route.path === '/' || route.path === '' || handler.slice(-6) === '.index'; + } + }); + } + hasRoute(route) { + return this.recognizer.hasRoute(route); + } + queryParamsTransition(changelist, wasTransitioning, oldState, newState) { + this.fireQueryParamDidChange(newState, changelist); + if (!wasTransitioning && this.activeTransition) { + // One of the routes in queryParamsDidChange + // caused a transition. Just return that transition. + return this.activeTransition; + } + else { + // Running queryParamsDidChange didn't change anything. + // Just update query params and be on our way. + // We have to return a noop transition that will + // perform a URL update at the end. This gives + // the user the ability to set the url update + // method (default is replaceState). + let newTransition = new Transition(this, undefined, undefined); + newTransition.queryParamsOnly = true; + oldState.queryParams = this.finalizeQueryParamChange(newState.routeInfos, newState.queryParams, newTransition); + newTransition[QUERY_PARAMS_SYMBOL] = newState.queryParams; + this.toReadOnlyInfos(newTransition, newState); + this.routeWillChange(newTransition); + newTransition.promise = newTransition.promise.then((result) => { + if (!newTransition.isAborted) { + this._updateURL(newTransition, oldState); + this.didTransition(this.currentRouteInfos); + this.toInfos(newTransition, newState.routeInfos, true); + this.routeDidChange(newTransition); + } + return result; + }, null, promiseLabel('Transition complete')); + return newTransition; + } + } + transitionByIntent(intent, isIntermediate) { + try { + return this.getTransitionByIntent(intent, isIntermediate); + } + catch (e) { + return new Transition(this, intent, undefined, e, undefined); + } + } + recognize(url) { + let intent = new URLTransitionIntent(this, url); + let newState = this.generateNewState(intent); + if (newState === null) { + return newState; + } + let readonlyInfos = toReadOnlyRouteInfo(newState.routeInfos, newState.queryParams); + return readonlyInfos[readonlyInfos.length - 1]; + } + recognizeAndLoad(url) { + let intent = new URLTransitionIntent(this, url); + let newState = this.generateNewState(intent); + if (newState === null) { + return Promise.reject(`URL ${url} was not recognized`); + } + let newTransition = new Transition(this, intent, newState, undefined); + return newTransition.then(() => { + let routeInfosWithAttributes = toReadOnlyRouteInfo(newState.routeInfos, newTransition[QUERY_PARAMS_SYMBOL], true); + return routeInfosWithAttributes[routeInfosWithAttributes.length - 1]; + }); + } + generateNewState(intent) { + try { + return intent.applyToState(this.state, false); + } + catch (e) { + return null; + } + } + getTransitionByIntent(intent, isIntermediate) { + let wasTransitioning = !!this.activeTransition; + let oldState = wasTransitioning ? this.activeTransition[STATE_SYMBOL] : this.state; + let newTransition; + let newState = intent.applyToState(oldState, isIntermediate); + let queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams); + if (routeInfosEqual(newState.routeInfos, oldState.routeInfos)) { + // This is a no-op transition. See if query params changed. + if (queryParamChangelist) { + let newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState); + newTransition.queryParamsOnly = true; + return newTransition; + } + // No-op. No need to create a new transition. + return this.activeTransition || new Transition(this, undefined, undefined); + } + if (isIntermediate) { + let transition = new Transition(this, undefined, newState); + transition.isIntermediate = true; + this.toReadOnlyInfos(transition, newState); + this.setupContexts(newState, transition); + this.routeWillChange(transition); + return this.activeTransition; + } + // Create a new transition to the destination route. + newTransition = new Transition(this, intent, newState, undefined, this.activeTransition); + // transition is to same route with same params, only query params differ. + // not caught above probably because refresh() has been used + if (routeInfosSameExceptQueryParams(newState.routeInfos, oldState.routeInfos)) { + newTransition.queryParamsOnly = true; + } + this.toReadOnlyInfos(newTransition, newState); + // Abort and usurp any previously active transition. + if (this.activeTransition) { + this.activeTransition.redirect(newTransition); + } + this.activeTransition = newTransition; + // Transition promises by default resolve with resolved state. + // For our purposes, swap out the promise to resolve + // after the transition has been finalized. + newTransition.promise = newTransition.promise.then((result) => { + return this.finalizeTransition(newTransition, result); + }, null, promiseLabel('Settle transition promise when transition is finalized')); + if (!wasTransitioning) { + this.notifyExistingHandlers(newState, newTransition); + } + this.fireQueryParamDidChange(newState, queryParamChangelist); + return newTransition; + } + /** + @private + + Begins and returns a Transition based on the provided + arguments. Accepts arguments in the form of both URL + transitions and named transitions. + + @param {Router} router + @param {Array[Object]} args arguments passed to transitionTo, + replaceWith, or handleURL + */ + doTransition(name, modelsArray = [], isIntermediate = false) { + let lastArg = modelsArray[modelsArray.length - 1]; + let queryParams = {}; + if (lastArg !== undefined && lastArg.hasOwnProperty('queryParams')) { + queryParams = modelsArray.pop().queryParams; + } + let intent; + if (name === undefined) { + log(this, 'Updating query params'); + // A query param update is really just a transition + // into the route you're already on. + let { routeInfos } = this.state; + intent = new NamedTransitionIntent(this, routeInfos[routeInfos.length - 1].name, undefined, [], queryParams); + } + else if (name.charAt(0) === '/') { + log(this, 'Attempting URL transition to ' + name); + intent = new URLTransitionIntent(this, name); + } + else { + log(this, 'Attempting transition to ' + name); + intent = new NamedTransitionIntent(this, name, undefined, modelsArray, queryParams); + } + return this.transitionByIntent(intent, isIntermediate); + } + /** + @private + + Updates the URL (if necessary) and calls `setupContexts` + to update the router's array of `currentRouteInfos`. + */ + finalizeTransition(transition, newState) { + try { + log(transition.router, transition.sequence, 'Resolved all models on destination route; finalizing transition.'); + let routeInfos = newState.routeInfos; + // Run all the necessary enter/setup/exit hooks + this.setupContexts(newState, transition); + // Check if a redirect occurred in enter/setup + if (transition.isAborted) { + // TODO: cleaner way? distinguish b/w targetRouteInfos? + this.state.routeInfos = this.currentRouteInfos; + return Promise.reject(logAbort(transition)); + } + this._updateURL(transition, newState); + transition.isActive = false; + this.activeTransition = undefined; + this.triggerEvent(this.currentRouteInfos, true, 'didTransition', []); + this.didTransition(this.currentRouteInfos); + this.toInfos(transition, newState.routeInfos, true); + this.routeDidChange(transition); + log(this, transition.sequence, 'TRANSITION COMPLETE.'); + // Resolve with the final route. + return routeInfos[routeInfos.length - 1].route; + } + catch (e) { + if (!isTransitionAborted(e)) { + let infos = transition[STATE_SYMBOL].routeInfos; + transition.trigger(true, 'error', e, transition, infos[infos.length - 1].route); + transition.abort(); + } + throw e; + } + } + /** + @private + + Takes an Array of `RouteInfo`s, figures out which ones are + exiting, entering, or changing contexts, and calls the + proper route hooks. + + For example, consider the following tree of routes. Each route is + followed by the URL segment it handles. + + ``` + |~index ("/") + | |~posts ("/posts") + | | |-showPost ("/:id") + | | |-newPost ("/new") + | | |-editPost ("/edit") + | |~about ("/about/:id") + ``` + + Consider the following transitions: + + 1. A URL transition to `/posts/1`. + 1. Triggers the `*model` callbacks on the + `index`, `posts`, and `showPost` routes + 2. Triggers the `enter` callback on the same + 3. Triggers the `setup` callback on the same + 2. A direct transition to `newPost` + 1. Triggers the `exit` callback on `showPost` + 2. Triggers the `enter` callback on `newPost` + 3. Triggers the `setup` callback on `newPost` + 3. A direct transition to `about` with a specified + context object + 1. Triggers the `exit` callback on `newPost` + and `posts` + 2. Triggers the `serialize` callback on `about` + 3. Triggers the `enter` callback on `about` + 4. Triggers the `setup` callback on `about` + + @param {Router} transition + @param {TransitionState} newState + */ + setupContexts(newState, transition) { + let partition = this.partitionRoutes(this.state, newState); + let i, l, route; + for (i = 0, l = partition.exited.length; i < l; i++) { + route = partition.exited[i].route; + delete route.context; + if (route !== undefined) { + if (route._internalReset !== undefined) { + route._internalReset(true, transition); + } + if (route.exit !== undefined) { + route.exit(transition); + } + } + } + let oldState = (this.oldState = this.state); + this.state = newState; + let currentRouteInfos = (this.currentRouteInfos = partition.unchanged.slice()); + try { + for (i = 0, l = partition.reset.length; i < l; i++) { + route = partition.reset[i].route; + if (route !== undefined) { + if (route._internalReset !== undefined) { + route._internalReset(false, transition); + } + } + } + for (i = 0, l = partition.updatedContext.length; i < l; i++) { + this.routeEnteredOrUpdated(currentRouteInfos, partition.updatedContext[i], false, transition); + } + for (i = 0, l = partition.entered.length; i < l; i++) { + this.routeEnteredOrUpdated(currentRouteInfos, partition.entered[i], true, transition); + } + } + catch (e) { + this.state = oldState; + this.currentRouteInfos = oldState.routeInfos; + throw e; + } + this.state.queryParams = this.finalizeQueryParamChange(currentRouteInfos, newState.queryParams, transition); + } + /** + @private + + Fires queryParamsDidChange event + */ + fireQueryParamDidChange(newState, queryParamChangelist) { + // If queryParams changed trigger event + if (queryParamChangelist) { + // This is a little hacky but we need some way of storing + // changed query params given that no activeTransition + // is guaranteed to have occurred. + this._changedQueryParams = queryParamChangelist.all; + this.triggerEvent(newState.routeInfos, true, 'queryParamsDidChange', [ + queryParamChangelist.changed, + queryParamChangelist.all, + queryParamChangelist.removed, + ]); + this._changedQueryParams = undefined; + } + } + /** + @private + + Helper method used by setupContexts. Handles errors or redirects + that may happen in enter/setup. + */ + routeEnteredOrUpdated(currentRouteInfos, routeInfo, enter, transition) { + let route = routeInfo.route, context = routeInfo.context; + function _routeEnteredOrUpdated(route) { + if (enter) { + if (route.enter !== undefined) { + route.enter(transition); + } + } + throwIfAborted(transition); + route.context = context; + if (route.contextDidChange !== undefined) { + route.contextDidChange(); + } + if (route.setup !== undefined) { + route.setup(context, transition); + } + throwIfAborted(transition); + currentRouteInfos.push(routeInfo); + return route; + } + // If the route doesn't exist, it means we haven't resolved the route promise yet + if (route === undefined) { + routeInfo.routePromise = routeInfo.routePromise.then(_routeEnteredOrUpdated); + } + else { + _routeEnteredOrUpdated(route); + } + return true; + } + /** + @private + + This function is called when transitioning from one URL to + another to determine which routes are no longer active, + which routes are newly active, and which routes remain + active but have their context changed. + + Take a list of old routes and new routes and partition + them into four buckets: + + * unchanged: the route was active in both the old and + new URL, and its context remains the same + * updated context: the route was active in both the + old and new URL, but its context changed. The route's + `setup` method, if any, will be called with the new + context. + * exited: the route was active in the old URL, but is + no longer active. + * entered: the route was not active in the old URL, but + is now active. + + The PartitionedRoutes structure has four fields: + + * `updatedContext`: a list of `RouteInfo` objects that + represent routes that remain active but have a changed + context + * `entered`: a list of `RouteInfo` objects that represent + routes that are newly active + * `exited`: a list of `RouteInfo` objects that are no + longer active. + * `unchanged`: a list of `RouteInfo` objects that remain active. + + @param {Array[InternalRouteInfo]} oldRoutes a list of the route + information for the previous URL (or `[]` if this is the + first handled transition) + @param {Array[InternalRouteInfo]} newRoutes a list of the route + information for the new URL + + @return {Partition} + */ + partitionRoutes(oldState, newState) { + let oldRouteInfos = oldState.routeInfos; + let newRouteInfos = newState.routeInfos; + let routes = { + updatedContext: [], + exited: [], + entered: [], + unchanged: [], + reset: [], + }; + let routeChanged, contextChanged = false, i, l; + for (i = 0, l = newRouteInfos.length; i < l; i++) { + let oldRouteInfo = oldRouteInfos[i], newRouteInfo = newRouteInfos[i]; + if (!oldRouteInfo || oldRouteInfo.route !== newRouteInfo.route) { + routeChanged = true; + } + if (routeChanged) { + routes.entered.push(newRouteInfo); + if (oldRouteInfo) { + routes.exited.unshift(oldRouteInfo); + } + } + else if (contextChanged || oldRouteInfo.context !== newRouteInfo.context) { + contextChanged = true; + routes.updatedContext.push(newRouteInfo); + } + else { + routes.unchanged.push(oldRouteInfo); + } + } + for (i = newRouteInfos.length, l = oldRouteInfos.length; i < l; i++) { + routes.exited.unshift(oldRouteInfos[i]); + } + routes.reset = routes.updatedContext.slice(); + routes.reset.reverse(); + return routes; + } + _updateURL(transition, state) { + let urlMethod = transition.urlMethod; + if (!urlMethod) { + return; + } + let { routeInfos } = state; + let { name: routeName } = routeInfos[routeInfos.length - 1]; + let params = {}; + for (let i = routeInfos.length - 1; i >= 0; --i) { + let routeInfo = routeInfos[i]; + merge(params, routeInfo.params); + if (routeInfo.route.inaccessibleByURL) { + urlMethod = null; + } + } + if (urlMethod) { + params.queryParams = transition._visibleQueryParams || state.queryParams; + let url = this.recognizer.generate(routeName, params); + // transitions during the initial transition must always use replaceURL. + // When the app boots, you are at a url, e.g. /foo. If some route + // redirects to bar as part of the initial transition, you don't want to + // add a history entry for /foo. If you do, pressing back will immediately + // hit the redirect again and take you back to /bar, thus killing the back + // button + let initial = transition.isCausedByInitialTransition; + // say you are at / and you click a link to route /foo. In /foo's + // route, the transition is aborted using replaceWith('/bar'). + // Because the current url is still /, the history entry for / is + // removed from the history. Clicking back will take you to the page + // you were on before /, which is often not even the app, thus killing + // the back button. That's why updateURL is always correct for an + // aborting transition that's not the initial transition + let replaceAndNotAborting = urlMethod === 'replace' && !transition.isCausedByAbortingTransition; + // because calling refresh causes an aborted transition, this needs to be + // special cased - if the initial transition is a replace transition, the + // urlMethod should be honored here. + let isQueryParamsRefreshTransition = transition.queryParamsOnly && urlMethod === 'replace'; + // say you are at / and you a `replaceWith(/foo)` is called. Then, that + // transition is aborted with `replaceWith(/bar)`. At the end, we should + // end up with /bar replacing /. We are replacing the replace. We only + // will replace the initial route if all subsequent aborts are also + // replaces. However, there is some ambiguity around the correct behavior + // here. + let replacingReplace = urlMethod === 'replace' && transition.isCausedByAbortingReplaceTransition; + if (initial || replaceAndNotAborting || isQueryParamsRefreshTransition || replacingReplace) { + this.replaceURL(url); + } + else { + this.updateURL(url); + } + } + } + finalizeQueryParamChange(resolvedHandlers, newQueryParams, transition) { + // We fire a finalizeQueryParamChange event which + // gives the new route hierarchy a chance to tell + // us which query params it's consuming and what + // their final values are. If a query param is + // no longer consumed in the final route hierarchy, + // its serialized segment will be removed + // from the URL. + for (let k in newQueryParams) { + if (newQueryParams.hasOwnProperty(k) && newQueryParams[k] === null) { + delete newQueryParams[k]; + } + } + let finalQueryParamsArray = []; + this.triggerEvent(resolvedHandlers, true, 'finalizeQueryParamChange', [ + newQueryParams, + finalQueryParamsArray, + transition, + ]); + if (transition) { + transition._visibleQueryParams = {}; + } + let finalQueryParams = {}; + for (let i = 0, len = finalQueryParamsArray.length; i < len; ++i) { + let qp = finalQueryParamsArray[i]; + finalQueryParams[qp.key] = qp.value; + if (transition && qp.visible !== false) { + transition._visibleQueryParams[qp.key] = qp.value; + } + } + return finalQueryParams; + } + toReadOnlyInfos(newTransition, newState) { + let oldRouteInfos = this.state.routeInfos; + this.fromInfos(newTransition, oldRouteInfos); + this.toInfos(newTransition, newState.routeInfos); + this._lastQueryParams = newState.queryParams; + } + fromInfos(newTransition, oldRouteInfos) { + if (newTransition !== undefined && oldRouteInfos.length > 0) { + let fromInfos = toReadOnlyRouteInfo(oldRouteInfos, Object.assign({}, this._lastQueryParams), true); + newTransition.from = fromInfos[fromInfos.length - 1] || null; + } + } + toInfos(newTransition, newRouteInfos, includeAttributes = false) { + if (newTransition !== undefined && newRouteInfos.length > 0) { + let toInfos = toReadOnlyRouteInfo(newRouteInfos, Object.assign({}, newTransition[QUERY_PARAMS_SYMBOL]), includeAttributes); + newTransition.to = toInfos[toInfos.length - 1] || null; + } + } + notifyExistingHandlers(newState, newTransition) { + let oldRouteInfos = this.state.routeInfos, i, oldRouteInfoLen, oldHandler, newRouteInfo; + oldRouteInfoLen = oldRouteInfos.length; + for (i = 0; i < oldRouteInfoLen; i++) { + oldHandler = oldRouteInfos[i]; + newRouteInfo = newState.routeInfos[i]; + if (!newRouteInfo || oldHandler.name !== newRouteInfo.name) { + break; + } + if (!newRouteInfo.isResolved) { + } + } + this.triggerEvent(oldRouteInfos, true, 'willTransition', [newTransition]); + this.routeWillChange(newTransition); + this.willTransition(oldRouteInfos, newState.routeInfos, newTransition); + } + /** + Clears the current and target route routes and triggers exit + on each of them starting at the leaf and traversing up through + its ancestors. + */ + reset() { + if (this.state) { + forEach(this.state.routeInfos.slice().reverse(), function (routeInfo) { + let route = routeInfo.route; + if (route !== undefined) { + if (route.exit !== undefined) { + route.exit(); + } + } + return true; + }); + } + this.oldState = undefined; + this.state = new TransitionState(); + this.currentRouteInfos = undefined; + } + /** + let handler = routeInfo.handler; + The entry point for handling a change to the URL (usually + via the back and forward button). + + Returns an Array of handlers and the parameters associated + with those parameters. + + @param {String} url a URL to process + + @return {Array} an Array of `[handler, parameter]` tuples + */ + handleURL(url) { + // Perform a URL-based transition, but don't change + // the URL afterward, since it already happened. + if (url.charAt(0) !== '/') { + url = '/' + url; + } + return this.doTransition(url).method(null); + } + /** + Transition into the specified named route. + + If necessary, trigger the exit callback on any routes + that are no longer represented by the target route. + + @param {String} name the name of the route + */ + transitionTo(name, ...contexts) { + if (typeof name === 'object') { + contexts.push(name); + return this.doTransition(undefined, contexts, false); + } + return this.doTransition(name, contexts); + } + intermediateTransitionTo(name, ...args) { + return this.doTransition(name, args, true); + } + refresh(pivotRoute) { + let previousTransition = this.activeTransition; + let state = previousTransition ? previousTransition[STATE_SYMBOL] : this.state; + let routeInfos = state.routeInfos; + if (pivotRoute === undefined) { + pivotRoute = routeInfos[0].route; + } + log(this, 'Starting a refresh transition'); + let name = routeInfos[routeInfos.length - 1].name; + let intent = new NamedTransitionIntent(this, name, pivotRoute, [], this._changedQueryParams || state.queryParams); + let newTransition = this.transitionByIntent(intent, false); + // if the previous transition is a replace transition, that needs to be preserved + if (previousTransition && previousTransition.urlMethod === 'replace') { + newTransition.method(previousTransition.urlMethod); + } + return newTransition; + } + /** + Identical to `transitionTo` except that the current URL will be replaced + if possible. + + This method is intended primarily for use with `replaceState`. + + @param {String} name the name of the route + */ + replaceWith(name) { + return this.doTransition(name).method('replace'); + } + /** + Take a named route and context objects and generate a + URL. + + @param {String} name the name of the route to generate + a URL for + @param {...Object} objects a list of objects to serialize + + @return {String} a URL + */ + generate(routeName, ...args) { + let partitionedArgs = extractQueryParams(args), suppliedParams = partitionedArgs[0], queryParams = partitionedArgs[1]; + // Construct a TransitionIntent with the provided params + // and apply it to the present state of the router. + let intent = new NamedTransitionIntent(this, routeName, undefined, suppliedParams); + let state = intent.applyToState(this.state, false); + let params = {}; + for (let i = 0, len = state.routeInfos.length; i < len; ++i) { + let routeInfo = state.routeInfos[i]; + let routeParams = routeInfo.serialize(); + merge(params, routeParams); + } + params.queryParams = queryParams; + return this.recognizer.generate(routeName, params); + } + applyIntent(routeName, contexts) { + let intent = new NamedTransitionIntent(this, routeName, undefined, contexts); + let state = (this.activeTransition && this.activeTransition[STATE_SYMBOL]) || this.state; + return intent.applyToState(state, false); + } + isActiveIntent(routeName, contexts, queryParams, _state) { + let state = _state || this.state, targetRouteInfos = state.routeInfos, routeInfo, len; + if (!targetRouteInfos.length) { + return false; + } + let targetHandler = targetRouteInfos[targetRouteInfos.length - 1].name; + let recognizerHandlers = this.recognizer.handlersFor(targetHandler); + let index = 0; + for (len = recognizerHandlers.length; index < len; ++index) { + routeInfo = targetRouteInfos[index]; + if (routeInfo.name === routeName) { + break; + } + } + if (index === recognizerHandlers.length) { + // The provided route name isn't even in the route hierarchy. + return false; + } + let testState = new TransitionState(); + testState.routeInfos = targetRouteInfos.slice(0, index + 1); + recognizerHandlers = recognizerHandlers.slice(0, index + 1); + let intent = new NamedTransitionIntent(this, targetHandler, undefined, contexts); + let newState = intent.applyToHandlers(testState, recognizerHandlers, targetHandler, true, true); + let routesEqual = routeInfosEqual(newState.routeInfos, testState.routeInfos); + if (!queryParams || !routesEqual) { + return routesEqual; + } + // Get a hash of QPs that will still be active on new route + let activeQPsOnNewHandler = {}; + merge(activeQPsOnNewHandler, queryParams); + let activeQueryParams = state.queryParams; + for (let key in activeQueryParams) { + if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) { + activeQPsOnNewHandler[key] = activeQueryParams[key]; + } + } + return routesEqual && !getChangelist(activeQPsOnNewHandler, queryParams); + } + isActive(routeName, ...args) { + let partitionedArgs = extractQueryParams(args); + return this.isActiveIntent(routeName, partitionedArgs[0], partitionedArgs[1]); + } + trigger(name, ...args) { + this.triggerEvent(this.currentRouteInfos, false, name, args); + } +} +function routeInfosEqual(routeInfos, otherRouteInfos) { + if (routeInfos.length !== otherRouteInfos.length) { + return false; + } + for (let i = 0, len = routeInfos.length; i < len; ++i) { + if (routeInfos[i] !== otherRouteInfos[i]) { + return false; + } + } + return true; +} +function routeInfosSameExceptQueryParams(routeInfos, otherRouteInfos) { + if (routeInfos.length !== otherRouteInfos.length) { + return false; + } + for (let i = 0, len = routeInfos.length; i < len; ++i) { + if (routeInfos[i].name !== otherRouteInfos[i].name) { + return false; + } + if (!paramsEqual(routeInfos[i].params, otherRouteInfos[i].params)) { + return false; + } + } + return true; +} +function paramsEqual(params, otherParams) { + if (!params && !otherParams) { + return true; + } + else if ((!params && !!otherParams) || (!!params && !otherParams)) { + // one is falsy but other is not; + return false; + } + let keys = Object.keys(params); + let otherKeys = Object.keys(otherParams); + if (keys.length !== otherKeys.length) { + return false; + } + for (let i = 0, len = keys.length; i < len; ++i) { + let key = keys[i]; + if (params[key] !== otherParams[key]) { + return false; + } + } + return true; +} + +export default Router; +export { Transition as InternalTransition, logAbort, STATE_SYMBOL, PARAMS_SYMBOL, QUERY_PARAMS_SYMBOL, TransitionState, TransitionError, InternalRouteInfo }; diff --git a/ember-vendored-pr-19806/dependencies/rsvp.js b/ember-vendored-pr-19806/dependencies/rsvp.js new file mode 100644 index 0000000..be54331 --- /dev/null +++ b/ember-vendored-pr-19806/dependencies/rsvp.js @@ -0,0 +1,2452 @@ +function callbacksFor(object) { + let callbacks = object._promiseCallbacks; + + if (!callbacks) { + callbacks = object._promiseCallbacks = {}; + } + + return callbacks; +} + +/** + @class EventTarget + @for rsvp + @public +*/ +var EventTarget = { + + /** + `EventTarget.mixin` extends an object with EventTarget methods. For + Example: + + ```javascript + import EventTarget from 'rsvp'; + + let object = {}; + + EventTarget.mixin(object); + + object.on('finished', function(event) { + // handle event + }); + + object.trigger('finished', { detail: value }); + ``` + + `EventTarget.mixin` also works with prototypes: + + ```javascript + import EventTarget from 'rsvp'; + + let Person = function() {}; + EventTarget.mixin(Person.prototype); + + let yehuda = new Person(); + let tom = new Person(); + + yehuda.on('poke', function(event) { + console.log('Yehuda says OW'); + }); + + tom.on('poke', function(event) { + console.log('Tom says OW'); + }); + + yehuda.trigger('poke'); + tom.trigger('poke'); + ``` + + @method mixin + @for rsvp + @private + @param {Object} object object to extend with EventTarget methods + */ + mixin(object) { + object.on = this.on; + object.off = this.off; + object.trigger = this.trigger; + object._promiseCallbacks = undefined; + return object; + }, + + /** + Registers a callback to be executed when `eventName` is triggered + + ```javascript + object.on('event', function(eventInfo){ + // handle the event + }); + + object.trigger('event'); + ``` + + @method on + @for EventTarget + @private + @param {String} eventName name of the event to listen for + @param {Function} callback function to be called when the event is triggered. + */ + on(eventName, callback) { + if (typeof callback !== 'function') { + throw new TypeError('Callback must be a function'); + } + + let allCallbacks = callbacksFor(this); + let callbacks = allCallbacks[eventName]; + + if (!callbacks) { + callbacks = allCallbacks[eventName] = []; + } + + if (callbacks.indexOf(callback) === -1) { + callbacks.push(callback); + } + }, + + /** + You can use `off` to stop firing a particular callback for an event: + + ```javascript + function doStuff() { // do stuff! } + object.on('stuff', doStuff); + + object.trigger('stuff'); // doStuff will be called + + // Unregister ONLY the doStuff callback + object.off('stuff', doStuff); + object.trigger('stuff'); // doStuff will NOT be called + ``` + + If you don't pass a `callback` argument to `off`, ALL callbacks for the + event will not be executed when the event fires. For example: + + ```javascript + let callback1 = function(){}; + let callback2 = function(){}; + + object.on('stuff', callback1); + object.on('stuff', callback2); + + object.trigger('stuff'); // callback1 and callback2 will be executed. + + object.off('stuff'); + object.trigger('stuff'); // callback1 and callback2 will not be executed! + ``` + + @method off + @for rsvp + @private + @param {String} eventName event to stop listening to + @param {Function} [callback] optional argument. If given, only the function + given will be removed from the event's callback queue. If no `callback` + argument is given, all callbacks will be removed from the event's callback + queue. + */ + off(eventName, callback) { + let allCallbacks = callbacksFor(this); + + if (!callback) { + allCallbacks[eventName] = []; + return; + } + + let callbacks = allCallbacks[eventName]; + let index = callbacks.indexOf(callback); + + if (index !== -1) { + callbacks.splice(index, 1); + } + }, + + /** + Use `trigger` to fire custom events. For example: + + ```javascript + object.on('foo', function(){ + console.log('foo event happened!'); + }); + object.trigger('foo'); + // 'foo event happened!' logged to the console + ``` + + You can also pass a value as a second argument to `trigger` that will be + passed as an argument to all event listeners for the event: + + ```javascript + object.on('foo', function(value){ + console.log(value.name); + }); + + object.trigger('foo', { name: 'bar' }); + // 'bar' logged to the console + ``` + + @method trigger + @for rsvp + @private + @param {String} eventName name of the event to be triggered + @param {*} [options] optional value to be passed to any event handlers for + the given `eventName` + */ + trigger(eventName, options, label) { + let allCallbacks = callbacksFor(this); + + let callbacks = allCallbacks[eventName]; + if (callbacks) { + // Don't cache the callbacks.length since it may grow + let callback; + for (let i = 0; i < callbacks.length; i++) { + callback = callbacks[i]; + callback(options, label); + } + } + } +}; + +const config = { + instrument: false +}; + +EventTarget['mixin'](config); + +function configure(name, value) { + if (arguments.length === 2) { + config[name] = value; + } else { + return config[name]; + } +} + +const queue = []; + +function scheduleFlush() { + setTimeout(() => { + for (let i = 0; i < queue.length; i++) { + let entry = queue[i]; + + let payload = entry.payload; + + payload.guid = payload.key + payload.id; + payload.childGuid = payload.key + payload.childId; + if (payload.error) { + payload.stack = payload.error.stack; + } + + config['trigger'](entry.name, entry.payload); + } + queue.length = 0; + }, 50); +} + +function instrument(eventName, promise, child) { + if (1 === queue.push({ + name: eventName, + payload: { + key: promise._guidKey, + id: promise._id, + eventName: eventName, + detail: promise._result, + childId: child && child._id, + label: promise._label, + timeStamp: Date.now(), + error: config["instrument-with-stack"] ? new Error(promise._label) : null + }})) { + scheduleFlush(); + } + } + +/** + `Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + import Promise from 'rsvp'; + + let promise = new Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + import Promise from 'rsvp'; + + let promise = RSVP.Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @for Promise + @static + @param {*} object value that the returned promise will be resolved with + @param {String} [label] optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` +*/ +function resolve$$1(object, label) { + /*jshint validthis:true */ + let Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + let promise = new Constructor(noop, label); + resolve$1(promise, object); + return promise; +} + +function withOwnPromise() { + return new TypeError('A promises callback cannot return that same promise.'); +} + +function objectOrFunction(x) { + let type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +} + +function noop() {} + +const PENDING = void 0; +const FULFILLED = 1; +const REJECTED = 2; + +function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { + try { + then$$1.call(value, fulfillmentHandler, rejectionHandler); + } catch(e) { + return e; + } +} +function handleForeignThenable(promise, thenable, then$$1) { + config.async(promise => { + let sealed = false; + let error = tryThen(then$$1, + thenable, + value => { + if (sealed) { return; } + sealed = true; + if (thenable === value) { + fulfill(promise, value); + } else { + resolve$1(promise, value); + } + }, + reason => { + if (sealed) { return; } + sealed = true; + + reject(promise, reason); + }, + 'Settle: ' + (promise._label || ' unknown promise') + ); + if (!sealed && error) { + sealed = true; + reject(promise, error); + } + }, promise); +} + +function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + thenable._onError = null; + reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, value => { + if (thenable === value) { + fulfill(promise, value); + } else { + resolve$1(promise, value); + } + }, reason => reject(promise, reason)); + } +} + +function handleMaybeThenable(promise, maybeThenable, then$$1) { + let isOwnThenable = + maybeThenable.constructor === promise.constructor && + then$$1 === then && + promise.constructor.resolve === resolve$$1; + + if (isOwnThenable) { + handleOwnThenable(promise, maybeThenable); + } else if (typeof then$$1 === 'function') { + handleForeignThenable(promise, maybeThenable, then$$1); + } else { + fulfill(promise, maybeThenable); + } +} + +function resolve$1(promise, value) { + if (promise === value) { + fulfill(promise, value); + } else if (objectOrFunction(value)) { + let then$$1; + try { + then$$1 = value.then; + } catch (error) { + reject(promise, error); + return; + } + handleMaybeThenable(promise, value, then$$1); + } else { + fulfill(promise, value); + } +} + +function publishRejection(promise) { + if (promise._onError) { + promise._onError(promise._result); + } + + publish(promise); +} + +function fulfill(promise, value) { + if (promise._state !== PENDING) { return; } + + promise._result = value; + promise._state = FULFILLED; + + if (promise._subscribers.length === 0) { + if (config.instrument) { + instrument('fulfilled', promise); + } + } else { + config.async(publish, promise); + } +} + +function reject(promise, reason) { + if (promise._state !== PENDING) { return; } + promise._state = REJECTED; + promise._result = reason; + config.async(publishRejection, promise); +} + +function subscribe(parent, child, onFulfillment, onRejection) { + let subscribers = parent._subscribers; + let length = subscribers.length; + + parent._onError = null; + + subscribers[length] = child; + subscribers[length + FULFILLED] = onFulfillment; + subscribers[length + REJECTED] = onRejection; + + if (length === 0 && parent._state) { + config.async(publish, parent); + } +} + +function publish(promise) { + let subscribers = promise._subscribers; + let settled = promise._state; + + if (config.instrument) { + instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); + } + + if (subscribers.length === 0) { return; } + + let child, callback, result = promise._result; + + for (let i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; + + if (child) { + invokeCallback(settled, child, callback, result); + } else { + callback(result); + } + } + + promise._subscribers.length = 0; +} + +function invokeCallback(state, promise, callback, result) { + let hasCallback = typeof callback === 'function'; + let value, succeeded = true, error; + + if (hasCallback) { + try { + value = callback(result); + } catch (e) { + succeeded = false; + error = e; + } + } else { + value = result; + } + + if (promise._state !== PENDING) { + // noop + } else if (value === promise) { + reject(promise, withOwnPromise()); + } else if (succeeded === false) { + reject(promise, error); + } else if (hasCallback) { + resolve$1(promise, value); + } else if (state === FULFILLED) { + fulfill(promise, value); + } else if (state === REJECTED) { + reject(promise, value); + } +} + +function initializePromise(promise, resolver) { + let resolved = false; + try { + resolver(value => { + if (resolved) { return; } + resolved = true; + resolve$1(promise, value); + }, reason => { + if (resolved) { return; } + resolved = true; + reject(promise, reason); + }); + } catch(e) { + reject(promise, e); + } +} + +function then(onFulfillment, onRejection, label) { + let parent = this; + let state = parent._state; + + if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { + config.instrument && instrument('chained', parent, parent); + return parent; + } + + parent._onError = null; + + let child = new parent.constructor(noop, label); + let result = parent._result; + + config.instrument && instrument('chained', parent, child); + + if (state === PENDING) { + subscribe(parent, child, onFulfillment, onRejection); + } else { + let callback = state === FULFILLED ? onFulfillment : onRejection; + config.async(() => invokeCallback(state, child, callback, result)); + } + + return child; +} + +class Enumerator { + constructor(Constructor, input, abortOnReject, label) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop, label); + this._abortOnReject = abortOnReject; + this._isUsingOwnPromise = Constructor === Promise; + this._isUsingOwnResolve = Constructor.resolve === resolve$$1; + + this._init(...arguments); + } + + _init(Constructor, input) { + let len = input.length || 0; + this.length = len; + this._remaining = len; + this._result = new Array(len); + + this._enumerate(input); + } + + _enumerate(input) { + let length = this.length; + let promise = this.promise; + + for (let i = 0; promise._state === PENDING && i < length; i++) { + this._eachEntry(input[i], i, true); + } + this._checkFullfillment(); + } + + _checkFullfillment() { + if (this._remaining === 0) { + let result = this._result; + fulfill(this.promise, result); + this._result = null; + } + } + + _settleMaybeThenable(entry, i, firstPass) { + let c = this._instanceConstructor; + + if (this._isUsingOwnResolve) { + let then$$1, error, succeeded = true; + try { + then$$1 = entry.then; + } catch (e) { + succeeded = false; + error = e; + } + + if (then$$1 === then && entry._state !== PENDING) { + entry._onError = null; + this._settledAt(entry._state, i, entry._result, firstPass); + } else if (typeof then$$1 !== 'function') { + this._settledAt(FULFILLED, i, entry, firstPass); + } else if (this._isUsingOwnPromise) { + let promise = new c(noop); + if (succeeded === false) { + reject(promise, error); + } else { + handleMaybeThenable(promise, entry, then$$1); + this._willSettleAt(promise, i, firstPass); + } + } else { + this._willSettleAt(new c(resolve => resolve(entry)), i, firstPass); + } + } else { + this._willSettleAt(c.resolve(entry), i, firstPass); + } + } + + _eachEntry(entry, i, firstPass) { + if (entry !== null && typeof entry === 'object') { + this._settleMaybeThenable(entry, i, firstPass); + } else { + this._setResultAt(FULFILLED, i, entry, firstPass); + } + } + + _settledAt(state, i, value, firstPass) { + let promise = this.promise; + + if (promise._state === PENDING) { + if (this._abortOnReject && state === REJECTED) { + reject(promise, value); + } else { + this._setResultAt(state, i, value, firstPass); + this._checkFullfillment(); + } + } + } + + _setResultAt(state, i, value, firstPass) { + this._remaining--; + this._result[i] = value; + } + + _willSettleAt(promise, i, firstPass) { + subscribe( + promise, undefined, + value => this._settledAt(FULFILLED, i, value, firstPass), + reason => this._settledAt(REJECTED, i, reason, firstPass) + ); + } +} + +function setSettledResult(state, i, value) { + this._remaining--; + if (state === FULFILLED) { + this._result[i] = { + state: 'fulfilled', + value: value + }; + } else { + this._result[i] = { + state: 'rejected', + reason: value + }; + } +} + +/** + `Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + import Promise, { resolve } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `RSVP.all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + import Promise, { resolve, reject } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = reject(new Error("2")); + let promise3 = reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @for Promise + @param {Array} entries array of promises + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static +*/ +function all(entries, label) { + if (!Array.isArray(entries)) { + return this.reject(new TypeError("Promise.all must be called with an array"), label); + } + return new Enumerator(this, entries, true /* abort on reject */, label).promise; +} + +/** + `Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + import Promise from 'rsvp'; + + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + import Promise from 'rsvp'; + + let promise1 = new Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + import Promise from 'rsvp'; + + Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @for Promise + @static + @param {Array} entries array of promises to observe + @param {String} [label] optional string for describing the promise returned. + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. +*/ +function race(entries, label) { + /*jshint validthis:true */ + let Constructor = this; + + let promise = new Constructor(noop, label); + + if (!Array.isArray(entries)) { + reject(promise, new TypeError('Promise.race must be called with an array')); + return promise; + } + + for (let i = 0; promise._state === PENDING && i < entries.length; i++) { + subscribe( + Constructor.resolve(entries[i]), undefined, + value => resolve$1(promise, value), + reason => reject(promise, reason) + ); + } + + return promise; +} + +/** + `Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + import Promise from 'rsvp'; + + let promise = new Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + import Promise from 'rsvp'; + + let promise = Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @for Promise + @static + @param {*} reason value that the returned promise will be rejected with. + @param {String} [label] optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. +*/ +function reject$1(reason, label) { + /*jshint validthis:true */ + let Constructor = this; + let promise = new Constructor(noop, label); + reject(promise, reason); + return promise; +} + +const guidKey = 'rsvp_' + Date.now() + '-'; +let counter = 0; + +function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); +} + +function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); +} + +/** + Promise objects represent the eventual result of an asynchronous operation. The + primary way of interacting with a promise is through its `then` method, which + registers callbacks to receive either a promise’s eventual value or the reason + why the promise cannot be fulfilled. + + Terminology + ----------- + + - `promise` is an object or function with a `then` method whose behavior conforms to this specification. + - `thenable` is an object or function that defines a `then` method. + - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). + - `exception` is a value that is thrown using the throw statement. + - `reason` is a value that indicates why a promise was rejected. + - `settled` the final resting state of a promise, fulfilled or rejected. + + A promise can be in one of three states: pending, fulfilled, or rejected. + + Promises that are fulfilled have a fulfillment value and are in the fulfilled + state. Promises that are rejected have a rejection reason and are in the + rejected state. A fulfillment value is never a thenable. + + Promises can also be said to *resolve* a value. If this value is also a + promise, then the original promise's settled state will match the value's + settled state. So a promise that *resolves* a promise that rejects will + itself reject, and a promise that *resolves* a promise that fulfills will + itself fulfill. + + + Basic Usage: + ------------ + + ```js + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(reason); + }); + + promise.then(function(value) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Advanced Usage: + --------------- + + Promises shine when abstracting away asynchronous interactions such as + `XMLHttpRequest`s. + + ```js + function getJSON(url) { + return new Promise(function(resolve, reject){ + let xhr = new XMLHttpRequest(); + + xhr.open('GET', url); + xhr.onreadystatechange = handler; + xhr.responseType = 'json'; + xhr.setRequestHeader('Accept', 'application/json'); + xhr.send(); + + function handler() { + if (this.readyState === this.DONE) { + if (this.status === 200) { + resolve(this.response); + } else { + reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); + } + } + }; + }); + } + + getJSON('/posts.json').then(function(json) { + // on fulfillment + }, function(reason) { + // on rejection + }); + ``` + + Unlike callbacks, promises are great composable primitives. + + ```js + Promise.all([ + getJSON('/posts'), + getJSON('/comments') + ]).then(function(values){ + values[0] // => postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @public + @param {function} resolver + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @constructor +*/ +class Promise { + constructor(resolver, label) { + this._id = counter++; + this._label = label; + this._state = undefined; + this._result = undefined; + this._subscribers = []; + + config.instrument && instrument('created', this); + + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } + } + + _onError(reason) { + config.after(() => { + if (this._onError) { + config.trigger('error', reason, this._label); + } + }); + } + +/** + `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same + as the catch block of a try/catch statement. + + ```js + function findAuthor(){ + throw new Error('couldn\'t find that author'); + } + + // synchronous + try { + findAuthor(); + } catch(reason) { + // something went wrong + } + + // async with promises + findAuthor().catch(function(reason){ + // something went wrong + }); + ``` + + @method catch + @param {Function} onRejection + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Promise} +*/ + catch(onRejection, label) { + return this.then(undefined, onRejection, label); + } + +/** + `finally` will be invoked regardless of the promise's fate just as native + try/catch/finally behaves + + Synchronous example: + + ```js + findAuthor() { + if (Math.random() > 0.5) { + throw new Error(); + } + return new Author(); + } + + try { + return findAuthor(); // succeed or fail + } catch(error) { + return findOtherAuthor(); + } finally { + // always runs + // doesn't affect the return value + } + ``` + + Asynchronous example: + + ```js + findAuthor().catch(function(reason){ + return findOtherAuthor(); + }).finally(function(){ + // author was either found, or not + }); + ``` + + @method finally + @param {Function} callback + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Promise} +*/ + finally(callback, label) { + let promise = this; + let constructor = promise.constructor; + + if (typeof callback === 'function') { + return promise.then(value => constructor.resolve(callback()).then(() => value), + reason => constructor.resolve(callback()).then(() => { throw reason; })); + } + + return promise.then(callback, callback); + } +} + +Promise.cast = resolve$$1; // deprecated +Promise.all = all; +Promise.race = race; +Promise.resolve = resolve$$1; +Promise.reject = reject$1; + +Promise.prototype._guidKey = guidKey; + +/** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` + + Chaining + -------- + + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. + + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); + + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we\'re unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we\'re unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. + + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` + + Assimilation + ------------ + + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // The user's comments are now available + }); + ``` + + If the assimliated promise rejects, then the downstream promise will also reject. + + ```js + findUser().then(function (user) { + return findCommentsByAuthor(user); + }).then(function (comments) { + // If `findCommentsByAuthor` fulfills, we'll have the value here + }, function (reason) { + // If `findCommentsByAuthor` rejects, we'll have the reason here + }); + ``` + + Simple Example + -------------- + + Synchronous Example + + ```javascript + let result; + + try { + result = findResult(); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + findResult(function(result, err){ + if (err) { + // failure + } else { + // success + } + }); + ``` + + Promise Example; + + ```javascript + findResult().then(function(result){ + // success + }, function(reason){ + // failure + }); + ``` + + Advanced Example + -------------- + + Synchronous Example + + ```javascript + let author, books; + + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` + + Errback Example + + ```js + + function foundBooks(books) { + + } + + function failure(reason) { + + } + + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure + } else { + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfillment + @param {Function} onRejection + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Promise} +*/ +Promise.prototype.then = then; + +function makeObject(_, argumentNames) { + let obj = {}; + let length = _.length; + let args = new Array(length); + + for (let x = 0; x < length; x++) { + args[x] = _[x]; + } + + for (let i = 0; i < argumentNames.length; i++) { + let name = argumentNames[i]; + obj[name] = args[i + 1]; + } + + return obj; +} + +function arrayResult(_) { + let length = _.length; + let args = new Array(length - 1); + + for (let i = 1; i < length; i++) { + args[i - 1] = _[i]; + } + + return args; +} + +function wrapThenable(then, promise) { + return { + then(onFulFillment, onRejection) { + return then.call(promise, onFulFillment, onRejection); + } + }; +} + +/** + `denodeify` takes a 'node-style' function and returns a function that + will return an `Promise`. You can use `denodeify` in Node.js or the + browser when you'd prefer to use promises over using callbacks. For example, + `denodeify` transforms the following: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ + if (err) return handleError(err); + handleData(data); + }); + ``` + + into: + + ```javascript + let fs = require('fs'); + let readFile = denodeify(fs.readFile); + + readFile('myfile.txt').then(handleData, handleError); + ``` + + If the node function has multiple success parameters, then `denodeify` + just returns the first one: + + ```javascript + let request = denodeify(require('request')); + + request('http://example.com').then(function(res) { + // ... + }); + ``` + + However, if you need all success parameters, setting `denodeify`'s + second parameter to `true` causes it to return all success parameters + as an array: + + ```javascript + let request = denodeify(require('request'), true); + + request('http://example.com').then(function(result) { + // result[0] -> res + // result[1] -> body + }); + ``` + + Or if you pass it an array with names it returns the parameters as a hash: + + ```javascript + let request = denodeify(require('request'), ['res', 'body']); + + request('http://example.com').then(function(result) { + // result.res + // result.body + }); + ``` + + Sometimes you need to retain the `this`: + + ```javascript + let app = require('express')(); + let render = denodeify(app.render.bind(app)); + ``` + + The denodified function inherits from the original function. It works in all + environments, except IE 10 and below. Consequently all properties of the original + function are available to you. However, any properties you change on the + denodeified function won't be changed on the original function. Example: + + ```javascript + let request = denodeify(require('request')), + cookieJar = request.jar(); // <- Inheritance is used here + + request('http://example.com', {jar: cookieJar}).then(function(res) { + // cookieJar.cookies holds now the cookies returned by example.com + }); + ``` + + Using `denodeify` makes it easier to compose asynchronous operations instead + of using callbacks. For example, instead of: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ + if (err) { ... } // Handle error + fs.writeFile('myfile2.txt', data, function(err){ + if (err) { ... } // Handle error + console.log('done') + }); + }); + ``` + + you can chain the operations together using `then` from the returned promise: + + ```javascript + let fs = require('fs'); + let readFile = denodeify(fs.readFile); + let writeFile = denodeify(fs.writeFile); + + readFile('myfile.txt').then(function(data){ + return writeFile('myfile2.txt', data); + }).then(function(){ + console.log('done') + }).catch(function(error){ + // Handle error + }); + ``` + + @method denodeify + @public + @static + @for rsvp + @param {Function} nodeFunc a 'node-style' function that takes a callback as + its last argument. The callback expects an error to be passed as its first + argument (if an error occurred, otherwise null), and the value from the + operation as its second argument ('function(err, value){ }'). + @param {Boolean|Array} [options] An optional paramter that if set + to `true` causes the promise to fulfill with the callback's success arguments + as an array. This is useful if the node function has multiple success + paramters. If you set this paramter to an array with names, the promise will + fulfill with a hash with these names as keys and the success parameters as + values. + @return {Function} a function that wraps `nodeFunc` to return a `Promise` +*/ +function denodeify(nodeFunc, options) { + let fn = function() { + let l = arguments.length; + let args = new Array(l + 1); + let promiseInput = false; + + for (let i = 0; i < l; ++i) { + let arg = arguments[i]; + + // TODO: this code really needs to be cleaned up + if (!promiseInput) { + if (arg !== null && typeof arg === 'object') { + if (arg.constructor === Promise) { + promiseInput = true; + } else { + try { + promiseInput = arg.then; + } catch(error) { + let p = new Promise(noop); + reject(p, error); + return p; + } + } + } else { + promiseInput = false; + } + if (promiseInput && promiseInput !== true) { + arg = wrapThenable(promiseInput, arg); + } + } + args[i] = arg; + } + + let promise = new Promise(noop); + + args[l] = function(err, val) { + if (err) { + reject(promise, err); + } else if (options === undefined) { + resolve$1(promise, val); + } else if (options === true) { + resolve$1(promise, arrayResult(arguments)); + } else if (Array.isArray(options)) { + resolve$1(promise, makeObject(arguments, options)); + } else { + resolve$1(promise, val); + } + }; + + if (promiseInput) { + return handlePromiseInput(promise, args, nodeFunc, this); + } else { + return handleValueInput(promise, args, nodeFunc, this); + } + }; + + fn.__proto__ = nodeFunc; + + return fn; +} + +function handleValueInput(promise, args, nodeFunc, self) { + try { + nodeFunc.apply(self, args); + } catch (error) { + reject(promise, error); + } + return promise; +} + +function handlePromiseInput(promise, args, nodeFunc, self){ + return Promise.all(args) + .then(args => handleValueInput(promise, args, nodeFunc, self)); +} + +/** + This is a convenient alias for `Promise.all`. + + @method all + @public + @static + @for rsvp + @param {Array} array Array of promises. + @param {String} [label] An optional label. This is useful + for tooling. +*/ +function all$1(array, label) { + return Promise.all(array, label); +} + +/** +@module rsvp +@public +**/ + +class AllSettled extends Enumerator { + constructor(Constructor, entries, label) { + super(Constructor, entries, false /* don't abort on reject */, label); + } +} + +AllSettled.prototype._setResultAt = setSettledResult; + + /** + `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing + a fail-fast method, it waits until all the promises have returned and + shows you all the results. This is useful if you want to handle multiple + promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled. The return promise is fulfilled with an array of the states of + the promises passed into the `promises` array argument. + + Each state object will either indicate fulfillment or rejection, and + provide the corresponding value or reason. The states will take one of + the following formats: + + ```javascript + { state: 'fulfilled', value: value } + or + { state: 'rejected', reason: reason } + ``` + + Example: + + ```javascript + let promise1 = RSVP.Promise.resolve(1); + let promise2 = RSVP.Promise.reject(new Error('2')); + let promise3 = RSVP.Promise.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.allSettled(promises).then(function(array){ + // array == [ + // { state: 'fulfilled', value: 1 }, + // { state: 'rejected', reason: Error }, + // { state: 'rejected', reason: Error } + // ] + // Note that for the second item, reason.message will be '2', and for the + // third item, reason.message will be '3'. + }, function(error) { + // Not run. (This block would only be called if allSettled had failed, + // for instance if passed an incorrect argument type.) + }); + ``` + + @method allSettled + @public + @static + @for rsvp + @param {Array} entries + @param {String} [label] - optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with an array of the settled + states of the constituent promises. + */ + +function allSettled(entries, label) { + if (!Array.isArray(entries)) { + return Promise.reject(new TypeError("Promise.allSettled must be called with an array"), label); + } + + return new AllSettled(Promise, entries, label).promise; +} + +/** + This is a convenient alias for `Promise.race`. + + @method race + @public + @static + @for rsvp + @param {Array} array Array of promises. + @param {String} [label] An optional label. This is useful + for tooling. + */ +function race$1(array, label) { + return Promise.race(array, label); +} + +class PromiseHash extends Enumerator { + constructor(Constructor, object, abortOnReject = true, label) { + super(Constructor, object, abortOnReject, label); + } + + _init(Constructor, object) { + this._result = {}; + this._enumerate(object); + } + + _enumerate(input) { + let keys = Object.keys(input); + + let length = keys.length; + let promise = this.promise; + this._remaining = length; + + let key, val; + for (let i = 0; promise._state === PENDING && i < length; i++) { + key = keys[i]; + val = input[key]; + this._eachEntry(val, key, true); + } + + this._checkFullfillment(); + } +} + +/** + `hash` is similar to `all`, but takes an object instead of an array + for its `promises` argument. + + Returns a promise that is fulfilled when all the given promises have been + fulfilled, or rejected if any of them become rejected. The returned promise + is fulfilled with a hash that has the same key names as the `promises` object + argument. If any of the values in the object are not promises, they will + simply be copied over to the fulfilled object. + + Example: + + ```javascript + let promises = { + myPromise: resolve(1), + yourPromise: resolve(2), + theirPromise: resolve(3), + notAPromise: 4 + }; + + hash(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: 1, + // yourPromise: 2, + // theirPromise: 3, + // notAPromise: 4 + // } + }); + ``` + + If any of the `promises` given to `hash` are rejected, the first promise + that is rejected will be given as the reason to the rejection handler. + + Example: + + ```javascript + let promises = { + myPromise: resolve(1), + rejectedPromise: reject(new Error('rejectedPromise')), + anotherRejectedPromise: reject(new Error('anotherRejectedPromise')), + }; + + hash(promises).then(function(hash){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === 'rejectedPromise' + }); + ``` + + An important note: `hash` is intended for plain JavaScript objects that + are just a set of keys and values. `hash` will NOT preserve prototype + chains. + + Example: + + ```javascript + import { hash, resolve } from 'rsvp'; + function MyConstructor(){ + this.example = resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + hash(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: 'Example' + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hash + @public + @static + @for rsvp + @param {Object} object + @param {String} [label] optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all properties of `promises` + have been fulfilled, or rejected if any of them become rejected. +*/ +function hash(object, label) { + return Promise.resolve(object, label) + .then(function(object) { + if (object === null || typeof object !== 'object') { + throw new TypeError("Promise.hash must be called with an object"); + } + return new PromiseHash(Promise, object, label).promise; + }); +} + +class HashSettled extends PromiseHash { + constructor(Constructor, object, label) { + super(Constructor, object, false, label); + } +} + +HashSettled.prototype._setResultAt = setSettledResult; + +/** + `hashSettled` is similar to `allSettled`, but takes an object + instead of an array for its `promises` argument. + + Unlike `all` or `hash`, which implement a fail-fast method, + but like `allSettled`, `hashSettled` waits until all the + constituent promises have returned and then shows you all the results + with their states and values/reasons. This is useful if you want to + handle multiple promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled, or rejected if the passed parameters are invalid. + + The returned promise is fulfilled with a hash that has the same key names as + the `promises` object argument. If any of the values in the object are not + promises, they will be copied over to the fulfilled object and marked with state + 'fulfilled'. + + Example: + + ```javascript + import { hashSettled, resolve } from 'rsvp'; + + let promises = { + myPromise: resolve(1), + yourPromise: resolve(2), + theirPromise: resolve(3), + notAPromise: 4 + }; + + hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // yourPromise: { state: 'fulfilled', value: 2 }, + // theirPromise: { state: 'fulfilled', value: 3 }, + // notAPromise: { state: 'fulfilled', value: 4 } + // } + }); + ``` + + If any of the `promises` given to `hash` are rejected, the state will + be set to 'rejected' and the reason for rejection provided. + + Example: + + ```javascript + import { hashSettled, reject, resolve } from 'rsvp'; + + let promises = { + myPromise: resolve(1), + rejectedPromise: reject(new Error('rejection')), + anotherRejectedPromise: reject(new Error('more rejection')), + }; + + hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // rejectedPromise: { state: 'rejected', reason: Error }, + // anotherRejectedPromise: { state: 'rejected', reason: Error }, + // } + // Note that for rejectedPromise, reason.message == 'rejection', + // and for anotherRejectedPromise, reason.message == 'more rejection'. + }); + ``` + + An important note: `hashSettled` is intended for plain JavaScript objects that + are just a set of keys and values. `hashSettled` will NOT preserve prototype + chains. + + Example: + + ```javascript + import Promise, { hashSettled, resolve } from 'rsvp'; + + function MyConstructor(){ + this.example = resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: Promise.resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + hashSettled(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: { state: 'fulfilled', value: 'Example' } + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hashSettled + @public + @for rsvp + @param {Object} object + @param {String} [label] optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when when all properties of `promises` + have been settled. + @static +*/ + +function hashSettled(object, label) { + return Promise.resolve(object, label) + .then(function(object) { + if (object === null || typeof object !== 'object') { + throw new TypeError("hashSettled must be called with an object"); + } + + return new HashSettled(Promise, object, false, label).promise; + }); +} + +/** + `rethrow` will rethrow an error on the next turn of the JavaScript event + loop in order to aid debugging. + + Promises A+ specifies that any exceptions that occur with a promise must be + caught by the promises implementation and bubbled to the last handler. For + this reason, it is recommended that you always specify a second rejection + handler function to `then`. However, `rethrow` will throw the exception + outside of the promise, so it bubbles up to your console if in the browser, + or domain/cause uncaught exception in Node. `rethrow` will also throw the + error again so the error can be handled by the promise per the spec. + + ```javascript + import { rethrow } from 'rsvp'; + + function throws(){ + throw new Error('Whoops!'); + } + + let promise = new Promise(function(resolve, reject){ + throws(); + }); + + promise.catch(rethrow).then(function(){ + // Code here doesn't run because the promise became rejected due to an + // error! + }, function (err){ + // handle the error here + }); + ``` + + The 'Whoops' error will be thrown on the next turn of the event loop + and you can watch for it in your console. You can also handle it using a + rejection handler given to `.then` or `.catch` on the returned promise. + + @method rethrow + @public + @static + @for rsvp + @param {Error} reason reason the promise became rejected. + @throws Error + @static +*/ +function rethrow(reason) { + setTimeout(() => { + throw reason; + }); + throw reason; +} + +/** + `defer` returns an object similar to jQuery's `$.Deferred`. + `defer` should be used when porting over code reliant on `$.Deferred`'s + interface. New code should use the `Promise` constructor instead. + + The object returned from `defer` is a plain object with three properties: + + * promise - an `Promise`. + * reject - a function that causes the `promise` property on this object to + become rejected + * resolve - a function that causes the `promise` property on this object to + become fulfilled. + + Example: + + ```javascript + let deferred = defer(); + + deferred.resolve("Success!"); + + deferred.promise.then(function(value){ + // value here is "Success!" + }); + ``` + + @method defer + @public + @static + @for rsvp + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Object} + */ + +function defer(label) { + let deferred = { resolve: undefined, reject: undefined }; + + deferred.promise = new Promise((resolve, reject) => { + deferred.resolve = resolve; + deferred.reject = reject; + }, label); + + return deferred; +} + +class MapEnumerator extends Enumerator { + constructor(Constructor, entries, mapFn, label) { + super(Constructor, entries, true, label, mapFn); + } + + _init(Constructor, input, bool, label, mapFn) { + let len = input.length || 0; + this.length = len; + this._remaining = len; + this._result = new Array(len); + this._mapFn = mapFn; + + this._enumerate(input); + } + + _setResultAt(state, i, value, firstPass) { + if (firstPass) { + try { + this._eachEntry(this._mapFn(value, i), i, false); + } catch (error) { + this._settledAt(REJECTED, i, error, false); + } + } else { + this._remaining--; + this._result[i] = value; + } + } +} + + +/** + `map` is similar to JavaScript's native `map` method. `mapFn` is eagerly called + meaning that as soon as any promise resolves its value will be passed to `mapFn`. + `map` returns a promise that will become fulfilled with the result of running + `mapFn` on the values the promises become fulfilled with. + + For example: + + ```javascript + import { map, resolve } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + map(promises, mapFn).then(function(result){ + // result is [ 2, 3, 4 ] + }); + ``` + + If any of the `promises` given to `map` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + import { map, reject, resolve } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = reject(new Error('2')); + let promise3 = reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + map(promises, mapFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `map` will also wait if a promise is returned from `mapFn`. For example, + say you want to get all comments from a set of blog posts, but you need + the blog posts first because they contain a url to those comments. + + ```javscript + import { map } from 'rsvp'; + + let mapFn = function(blogPost){ + // getComments does some ajax and returns an Promise that is fulfilled + // with some comments data + return getComments(blogPost.comments_url); + }; + + // getBlogPosts does some ajax and returns an Promise that is fulfilled + // with some blog post data + map(getBlogPosts(), mapFn).then(function(comments){ + // comments is the result of asking the server for the comments + // of all blog posts returned from getBlogPosts() + }); + ``` + + @method map + @public + @static + @for rsvp + @param {Array} promises + @param {Function} mapFn function to be called on each fulfilled promise. + @param {String} [label] optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with the result of calling + `mapFn` on each fulfilled promise or value when they become fulfilled. + The promise will be rejected if any of the given `promises` become rejected. +*/ +function map(promises, mapFn, label) { + if (typeof mapFn !== 'function') { + return Promise.reject(new TypeError("map expects a function as a second argument"), label); + } + + return Promise.resolve(promises, label) + .then(function(promises) { + if (!Array.isArray(promises)) { + throw new TypeError("map must be called with an array"); + } + return new MapEnumerator(Promise, promises, mapFn, label).promise; + }); +} + +/** + This is a convenient alias for `Promise.resolve`. + + @method resolve + @public + @static + @for rsvp + @param {*} value value that the returned promise will be resolved with + @param {String} [label] optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` +*/ +function resolve$2(value, label) { + return Promise.resolve(value, label); +} + +/** + This is a convenient alias for `Promise.reject`. + + @method reject + @public + @static + @for rsvp + @param {*} reason value that the returned promise will be rejected with. + @param {String} [label] optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. +*/ +function reject$2(reason, label) { + return Promise.reject(reason, label); +} + +const EMPTY_OBJECT = {}; + +class FilterEnumerator extends MapEnumerator { + + _checkFullfillment() { + if (this._remaining === 0 && this._result !== null) { + let result = this._result.filter((val) => val !== EMPTY_OBJECT); + fulfill(this.promise, result); + this._result = null; + } + } + + _setResultAt(state, i, value, firstPass) { + if (firstPass) { + this._result[i] = value; + let val, succeeded = true; + try { + val = this._mapFn(value, i); + } catch (error) { + succeeded = false; + this._settledAt(REJECTED, i, error, false); + } + if (succeeded) { + this._eachEntry(val, i, false); + } + } else { + this._remaining--; + if (!value) { + this._result[i] = EMPTY_OBJECT; + } + } + } +} + +/** + `filter` is similar to JavaScript's native `filter` method. + `filterFn` is eagerly called meaning that as soon as any promise + resolves its value will be passed to `filterFn`. `filter` returns + a promise that will become fulfilled with the result of running + `filterFn` on the values the promises become fulfilled with. + + For example: + + ```javascript + import { filter, resolve } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = resolve(2); + let promise3 = resolve(3); + + let promises = [promise1, promise2, promise3]; + + let filterFn = function(item){ + return item > 1; + }; + + filter(promises, filterFn).then(function(result){ + // result is [ 2, 3 ] + }); + ``` + + If any of the `promises` given to `filter` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + import { filter, reject, resolve } from 'rsvp'; + + let promise1 = resolve(1); + let promise2 = reject(new Error('2')); + let promise3 = reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let filterFn = function(item){ + return item > 1; + }; + + filter(promises, filterFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `filter` will also wait for any promises returned from `filterFn`. + For instance, you may want to fetch a list of users then return a subset + of those users based on some asynchronous operation: + + ```javascript + import { filter, resolve } from 'rsvp'; + + let alice = { name: 'alice' }; + let bob = { name: 'bob' }; + let users = [ alice, bob ]; + + let promises = users.map(function(user){ + return resolve(user); + }); + + let filterFn = function(user){ + // Here, Alice has permissions to create a blog post, but Bob does not. + return getPrivilegesForUser(user).then(function(privs){ + return privs.can_create_blog_post === true; + }); + }; + filter(promises, filterFn).then(function(users){ + // true, because the server told us only Alice can create a blog post. + users.length === 1; + // false, because Alice is the only user present in `users` + users[0] === bob; + }); + ``` + + @method filter + @public + @static + @for rsvp + @param {Array} promises + @param {Function} filterFn - function to be called on each resolved value to + filter the final results. + @param {String} [label] optional string describing the promise. Useful for + tooling. + @return {Promise} +*/ + +function filter(promises, filterFn, label) { + if (typeof filterFn !== 'function') { + return Promise.reject(new TypeError("filter expects function as a second argument"), label); + } + + return Promise.resolve(promises, label) + .then(function(promises) { + if (!Array.isArray(promises)) { + throw new TypeError("filter must be called with an array"); + } + return new FilterEnumerator(Promise, promises, filterFn, label).promise; + }); +} + +let len = 0; +let vertxNext; +function asap(callback, arg) { + queue$1[len] = callback; + queue$1[len + 1] = arg; + len += 2; + if (len === 2) { + // If len is 1, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + scheduleFlush$1(); + } +} + +const browserWindow = (typeof window !== 'undefined') ? window : undefined; +const browserGlobal = browserWindow || {}; +const BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; +const isNode = typeof self === 'undefined' && + typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; + +// test for web worker but not in IE10 +const isWorker = typeof Uint8ClampedArray !== 'undefined' && + typeof importScripts !== 'undefined' && + typeof MessageChannel !== 'undefined'; + +// node +function useNextTick() { + let nextTick = process.nextTick; + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // setImmediate should be used instead instead + let version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); + if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { + nextTick = setImmediate; + } + return () => nextTick(flush); +} + +// vertx +function useVertxTimer() { + if (typeof vertxNext !== 'undefined') { + return function() { + vertxNext(flush); + }; + } + return useSetTimeout(); +} + +function useMutationObserver() { + let iterations = 0; + let observer = new BrowserMutationObserver(flush); + let node = document.createTextNode(''); + observer.observe(node, { characterData: true }); + + return () => node.data = (iterations = ++iterations % 2); +} + +// web worker +function useMessageChannel() { + let channel = new MessageChannel(); + channel.port1.onmessage = flush; + return () => channel.port2.postMessage(0); +} + +function useSetTimeout() { + return () => setTimeout(flush, 1); +} + +const queue$1 = new Array(1000); + +function flush() { + for (let i = 0; i < len; i+=2) { + let callback = queue$1[i]; + let arg = queue$1[i+1]; + + callback(arg); + + queue$1[i] = undefined; + queue$1[i+1] = undefined; + } + + len = 0; +} + +function attemptVertex() { + try { + const vertx = Function('return this')().require('vertx'); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch(e) { + return useSetTimeout(); + } +} + +let scheduleFlush$1; +// Decide what async method to use to triggering processing of queued callbacks: +if (isNode) { + scheduleFlush$1 = useNextTick(); +} else if (BrowserMutationObserver) { + scheduleFlush$1 = useMutationObserver(); +} else if (isWorker) { + scheduleFlush$1 = useMessageChannel(); +} else if (browserWindow === undefined && typeof require === 'function') { + scheduleFlush$1 = attemptVertex(); +} else { + scheduleFlush$1 = useSetTimeout(); +} + +// defaults +config.async = asap; +config.after = cb => setTimeout(cb, 0); +const cast = resolve$2; + +const async = (callback, arg) => config.async(callback, arg); + +function on() { + config.on(...arguments); +} + +function off() { + config.off(...arguments); +} + +// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` +if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { + let callbacks = window['__PROMISE_INSTRUMENTATION__']; + configure('instrument', true); + for (let eventName in callbacks) { + if (callbacks.hasOwnProperty(eventName)) { + on(eventName, callbacks[eventName]); + } + } +} + +// the default export here is for backwards compat: +// https://github.com/tildeio/rsvp.js/issues/434 +var rsvp = { + asap, + cast, + Promise, + EventTarget, + all: all$1, + allSettled, + race: race$1, + hash, + hashSettled, + rethrow, + defer, + denodeify, + configure, + on, + off, + resolve: resolve$2, + reject: reject$2, + map, + async, + filter +}; + +export default rsvp; +export { asap, cast, Promise, EventTarget, all$1 as all, allSettled, race$1 as race, hash, hashSettled, rethrow, defer, denodeify, configure, on, off, resolve$2 as resolve, reject$2 as reject, map, async, filter }; diff --git a/ember-vendored-pr-19806/ember-template-compiler.js b/ember-vendored-pr-19806/ember-template-compiler.js new file mode 100644 index 0000000..57ed738 --- /dev/null +++ b/ember-vendored-pr-19806/ember-template-compiler.js @@ -0,0 +1,21896 @@ +(function() { +/*! + * @overview Ember - JavaScript Application Framework + * @copyright Copyright 2011-2021 Tilde Inc. and contributors + * Portions Copyright 2006-2011 Strobe Inc. + * Portions Copyright 2008-2011 Apple Inc. All rights reserved. + * @license Licensed under MIT license + * See https://raw.github.com/emberjs/ember.js/master/LICENSE + * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74 + */ + +/* eslint-disable no-var */ +/* globals global globalThis self */ +/* eslint-disable-next-line no-unused-vars */ +var define, require; + +(function () { + var globalObj = + typeof globalThis !== 'undefined' + ? globalThis + : typeof self !== 'undefined' + ? self + : typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' + ? global + : null; + + if (globalObj === null) { + throw new Error('unable to locate global object'); + } + + if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') { + define = globalObj.define; + require = globalObj.require; + + return; + } + + var registry = Object.create(null); + var seen = Object.create(null); + + function missingModule(name, referrerName) { + if (referrerName) { + throw new Error('Could not find module ' + name + ' required by: ' + referrerName); + } else { + throw new Error('Could not find module ' + name); + } + } + + function internalRequire(_name, referrerName) { + var name = _name; + var mod = registry[name]; + + if (!mod) { + name = name + '/index'; + mod = registry[name]; + } + + var exports = seen[name]; + + if (exports !== undefined) { + return exports; + } + + exports = seen[name] = {}; + + if (!mod) { + missingModule(_name, referrerName); + } + + var deps = mod.deps; + var callback = mod.callback; + var reified = new Array(deps.length); + + for (var i = 0; i < deps.length; i++) { + if (deps[i] === 'exports') { + reified[i] = exports; + } else if (deps[i] === 'require') { + reified[i] = require; + } else { + reified[i] = require(deps[i], name); + } + } + + callback.apply(this, reified); + + return exports; + } + + require = function (name) { + return internalRequire(name, null); + }; + + // eslint-disable-next-line no-unused-vars + define = function (name, deps, callback) { + registry[name] = { deps: deps, callback: callback }; + }; + + // setup `require` module + require['default'] = require; + + require.has = function registryHas(moduleName) { + return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']); + }; + + require._eak_seen = require.entries = registry; +})(); + +define("@ember/-internals/browser-environment/index", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.hasDOM = _exports.isIE = _exports.isFirefox = _exports.isChrome = _exports.userAgent = _exports.history = _exports.location = _exports.window = void 0; + // check if window exists and actually is the global + var hasDom = typeof self === 'object' && self !== null && self.Object === Object && typeof Window !== 'undefined' && self.constructor === Window && typeof document === 'object' && document !== null && self.document === document && typeof location === 'object' && location !== null && self.location === location && typeof history === 'object' && history !== null && self.history === history && typeof navigator === 'object' && navigator !== null && self.navigator === navigator && typeof navigator.userAgent === 'string'; + _exports.hasDOM = hasDom; + var window = hasDom ? self : null; + _exports.window = window; + var location$1 = hasDom ? self.location : null; + _exports.location = location$1; + var history$1 = hasDom ? self.history : null; + _exports.history = history$1; + var userAgent = hasDom ? self.navigator.userAgent : 'Lynx (textmode)'; + _exports.userAgent = userAgent; + var isChrome = hasDom ? typeof chrome === 'object' && !(typeof opera === 'object') : false; + _exports.isChrome = isChrome; + var isFirefox = hasDom ? typeof InstallTrigger !== 'undefined' : false; + _exports.isFirefox = isFirefox; + var isIE = hasDom ? typeof MSInputMethodContext !== 'undefined' && typeof documentMode !== 'undefined' : false; + _exports.isIE = isIE; +}); +define("@ember/-internals/environment/index", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.getLookup = getLookup; + _exports.setLookup = setLookup; + _exports.getENV = getENV; + _exports.ENV = _exports.context = _exports.global = void 0; + + // from lodash to catch fake globals + function checkGlobal(value) { + return value && value.Object === Object ? value : undefined; + } // element ids can ruin global miss checks + + + function checkElementIdShadowing(value) { + return value && value.nodeType === undefined ? value : undefined; + } // export real global + + + var global$1 = checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) || checkGlobal(typeof self === 'object' && self) || checkGlobal(typeof window === 'object' && window) || typeof mainContext !== 'undefined' && mainContext || // set before strict mode in Ember loader/wrapper + new Function('return this')(); // eval outside of strict mode + + _exports.global = global$1; + + var context = function (global, Ember) { + return Ember === undefined ? { + imports: global, + exports: global, + lookup: global + } : { + // import jQuery + imports: Ember.imports || global, + // export Ember + exports: Ember.exports || global, + // search for Namespaces + lookup: Ember.lookup || global + }; + }(global$1, global$1.Ember); + + _exports.context = context; + + function getLookup() { + return context.lookup; + } + + function setLookup(value) { + context.lookup = value; + } + /** + The hash of environment variables used to control various configuration + settings. To specify your own or override default settings, add the + desired properties to a global hash named `EmberENV` (or `ENV` for + backwards compatibility with earlier versions of Ember). The `EmberENV` + hash must be created before loading Ember. + + @class EmberENV + @type Object + @public + */ + + + var ENV = { + ENABLE_OPTIONAL_FEATURES: false, + + /** + Determines whether Ember should add to `Array` + native object prototypes, a few extra methods in order to provide a more + friendly API. + We generally recommend leaving this option set to true however, if you need + to turn it off, you can add the configuration property + `EXTEND_PROTOTYPES` to `EmberENV` and set it to `false`. + Note, when disabled (the default configuration for Ember Addons), you will + instead have to access all methods and functions from the Ember + namespace. + @property EXTEND_PROTOTYPES + @type Boolean + @default true + @for EmberENV + @public + */ + EXTEND_PROTOTYPES: { + Array: true + }, + + /** + The `LOG_STACKTRACE_ON_DEPRECATION` property, when true, tells Ember to log + a full stack trace during deprecation warnings. + @property LOG_STACKTRACE_ON_DEPRECATION + @type Boolean + @default true + @for EmberENV + @public + */ + LOG_STACKTRACE_ON_DEPRECATION: true, + + /** + The `LOG_VERSION` property, when true, tells Ember to log versions of all + dependent libraries in use. + @property LOG_VERSION + @type Boolean + @default true + @for EmberENV + @public + */ + LOG_VERSION: true, + RAISE_ON_DEPRECATION: false, + STRUCTURED_PROFILE: false, + + /** + Whether to insert a `
` wrapper around the + application template. See RFC #280. + This is not intended to be set directly, as the implementation may change in + the future. Use `@ember/optional-features` instead. + @property _APPLICATION_TEMPLATE_WRAPPER + @for EmberENV + @type Boolean + @default true + @private + */ + _APPLICATION_TEMPLATE_WRAPPER: true, + + /** + Whether to use Glimmer Component semantics (as opposed to the classic "Curly" + components semantics) for template-only components. See RFC #278. + This is not intended to be set directly, as the implementation may change in + the future. Use `@ember/optional-features` instead. + @property _TEMPLATE_ONLY_GLIMMER_COMPONENTS + @for EmberENV + @type Boolean + @default false + @private + */ + _TEMPLATE_ONLY_GLIMMER_COMPONENTS: false, + + /** + Whether to perform extra bookkeeping needed to make the `captureRenderTree` + API work. + This has to be set before the ember JavaScript code is evaluated. This is + usually done by setting `window.EmberENV = { _DEBUG_RENDER_TREE: true };` + before the "vendor" `'; + }; + + return EventedTokenizer; + }(); + + _exports.EventedTokenizer = EventedTokenizer; + + var Tokenizer = + /** @class */ + function () { + function Tokenizer(entityParser, options) { + if (options === void 0) { + options = {}; + } + + this.options = options; + this.token = null; + this.startLine = 1; + this.startColumn = 0; + this.tokens = []; + this.tokenizer = new EventedTokenizer(this, entityParser, options.mode); + this._currentAttribute = undefined; + } + + Tokenizer.prototype.tokenize = function (input) { + this.tokens = []; + this.tokenizer.tokenize(input); + return this.tokens; + }; + + Tokenizer.prototype.tokenizePart = function (input) { + this.tokens = []; + this.tokenizer.tokenizePart(input); + return this.tokens; + }; + + Tokenizer.prototype.tokenizeEOF = function () { + this.tokens = []; + this.tokenizer.tokenizeEOF(); + return this.tokens[0]; + }; + + Tokenizer.prototype.reset = function () { + this.token = null; + this.startLine = 1; + this.startColumn = 0; + }; + + Tokenizer.prototype.current = function () { + var token = this.token; + + if (token === null) { + throw new Error('token was unexpectedly null'); + } + + if (arguments.length === 0) { + return token; + } + + for (var i = 0; i < arguments.length; i++) { + if (token.type === arguments[i]) { + return token; + } + } + + throw new Error("token type was unexpectedly " + token.type); + }; + + Tokenizer.prototype.push = function (token) { + this.token = token; + this.tokens.push(token); + }; + + Tokenizer.prototype.currentAttribute = function () { + return this._currentAttribute; + }; + + Tokenizer.prototype.addLocInfo = function () { + if (this.options.loc) { + this.current().loc = { + start: { + line: this.startLine, + column: this.startColumn + }, + end: { + line: this.tokenizer.line, + column: this.tokenizer.column + } + }; + } + + this.startLine = this.tokenizer.line; + this.startColumn = this.tokenizer.column; + }; // Data + + + Tokenizer.prototype.beginData = function () { + this.push({ + type: "Chars" + /* Chars */ + , + chars: '' + }); + }; + + Tokenizer.prototype.appendToData = function (char) { + this.current("Chars" + /* Chars */ + ).chars += char; + }; + + Tokenizer.prototype.finishData = function () { + this.addLocInfo(); + }; // Comment + + + Tokenizer.prototype.beginComment = function () { + this.push({ + type: "Comment" + /* Comment */ + , + chars: '' + }); + }; + + Tokenizer.prototype.appendToCommentData = function (char) { + this.current("Comment" + /* Comment */ + ).chars += char; + }; + + Tokenizer.prototype.finishComment = function () { + this.addLocInfo(); + }; // Tags - basic + + + Tokenizer.prototype.tagOpen = function () {}; + + Tokenizer.prototype.beginStartTag = function () { + this.push({ + type: "StartTag" + /* StartTag */ + , + tagName: '', + attributes: [], + selfClosing: false + }); + }; + + Tokenizer.prototype.beginEndTag = function () { + this.push({ + type: "EndTag" + /* EndTag */ + , + tagName: '' + }); + }; + + Tokenizer.prototype.finishTag = function () { + this.addLocInfo(); + }; + + Tokenizer.prototype.markTagAsSelfClosing = function () { + this.current("StartTag" + /* StartTag */ + ).selfClosing = true; + }; // Tags - name + + + Tokenizer.prototype.appendToTagName = function (char) { + this.current("StartTag" + /* StartTag */ + , "EndTag" + /* EndTag */ + ).tagName += char; + }; // Tags - attributes + + + Tokenizer.prototype.beginAttribute = function () { + this._currentAttribute = ['', '', false]; + }; + + Tokenizer.prototype.appendToAttributeName = function (char) { + this.currentAttribute()[0] += char; + }; + + Tokenizer.prototype.beginAttributeValue = function (isQuoted) { + this.currentAttribute()[2] = isQuoted; + }; + + Tokenizer.prototype.appendToAttributeValue = function (char) { + this.currentAttribute()[1] += char; + }; + + Tokenizer.prototype.finishAttributeValue = function () { + this.current("StartTag" + /* StartTag */ + ).attributes.push(this._currentAttribute); + }; + + Tokenizer.prototype.reportSyntaxError = function (message) { + this.current().syntaxError = message; + }; + + return Tokenizer; + }(); + + _exports.Tokenizer = Tokenizer; + + function tokenize(input, options) { + var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options); + return tokenizer.tokenize(input); + } +}); +(function (m) { if (typeof module === "object" && module.exports) { module.exports = m } }(require("ember-template-compiler"))); +}()); +//# sourceMappingURL=ember-template-compiler.map diff --git a/ember-vendored-pr-19806/ember-template-compiler.map b/ember-vendored-pr-19806/ember-template-compiler.map new file mode 100644 index 0000000..857fbac --- /dev/null +++ b/ember-vendored-pr-19806/ember-template-compiler.map @@ -0,0 +1 @@ +{"version":3,"sources":["license.js","loader.js","@ember/-internals/browser-environment/index.js","@ember/-internals/environment/index.js","@ember/-internals/utils/index.js","@ember/canary-features/index.js","@ember/debug/container-debug-adapter.js","@ember/debug/data-adapter.js","@ember/debug/index.js","@ember/debug/lib/capture-render-tree.js","@ember/debug/lib/deprecate.js","@ember/debug/lib/handlers.js","@ember/debug/lib/testing.js","@ember/debug/lib/warn.js","@ember/deprecated-features/index.js","@ember/error/index.js","@ember/polyfills/index.js","@ember/polyfills/lib/assign.js","@glimmer/compiler.js","@glimmer/env.js","@glimmer/syntax.js","@glimmer/util.js","@glimmer/wire-format.js","@handlebars/parser/index.js","ember-babel.js","ember-template-compiler/index.js","ember-template-compiler/lib/plugins/assert-against-attrs.js","ember-template-compiler/lib/plugins/assert-against-dynamic-helpers-modifiers.js","ember-template-compiler/lib/plugins/assert-against-named-blocks.js","ember-template-compiler/lib/plugins/assert-against-named-outlets.js","ember-template-compiler/lib/plugins/assert-input-helper-without-block.js","ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js","ember-template-compiler/lib/plugins/assert-splattribute-expression.js","ember-template-compiler/lib/plugins/index.js","ember-template-compiler/lib/plugins/transform-action-syntax.js","ember-template-compiler/lib/plugins/transform-each-in-into-each.js","ember-template-compiler/lib/plugins/transform-each-track-array.js","ember-template-compiler/lib/plugins/transform-in-element.js","ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js","ember-template-compiler/lib/plugins/transform-resolutions.js","ember-template-compiler/lib/plugins/transform-wrap-mount-and-outlet.js","ember-template-compiler/lib/plugins/utils.js","ember-template-compiler/lib/system/bootstrap.js","ember-template-compiler/lib/system/calculate-location-display.js","ember-template-compiler/lib/system/compile-options.js","ember-template-compiler/lib/system/compile.js","ember-template-compiler/lib/system/dasherize-component-name.js","ember-template-compiler/lib/system/initializer.js","ember-template-compiler/lib/system/precompile.js","ember/version.js","simple-html-tokenizer.js"],"sourcesContent":["/*!\n * @overview Ember - JavaScript Application Framework\n * @copyright Copyright 2011-2021 Tilde Inc. and contributors\n * Portions Copyright 2006-2011 Strobe Inc.\n * Portions Copyright 2008-2011 Apple Inc. All rights reserved.\n * @license Licensed under MIT license\n * See https://raw.github.com/emberjs/ember.js/master/LICENSE\n * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74\n */\n","/* eslint-disable no-var */\n/* globals global globalThis self */\n/* eslint-disable-next-line no-unused-vars */\nvar define, require;\n\n(function () {\n var globalObj =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : null;\n\n if (globalObj === null) {\n throw new Error('unable to locate global object');\n }\n\n if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') {\n define = globalObj.define;\n require = globalObj.require;\n\n return;\n }\n\n var registry = Object.create(null);\n var seen = Object.create(null);\n\n function missingModule(name, referrerName) {\n if (referrerName) {\n throw new Error('Could not find module ' + name + ' required by: ' + referrerName);\n } else {\n throw new Error('Could not find module ' + name);\n }\n }\n\n function internalRequire(_name, referrerName) {\n var name = _name;\n var mod = registry[name];\n\n if (!mod) {\n name = name + '/index';\n mod = registry[name];\n }\n\n var exports = seen[name];\n\n if (exports !== undefined) {\n return exports;\n }\n\n exports = seen[name] = {};\n\n if (!mod) {\n missingModule(_name, referrerName);\n }\n\n var deps = mod.deps;\n var callback = mod.callback;\n var reified = new Array(deps.length);\n\n for (var i = 0; i < deps.length; i++) {\n if (deps[i] === 'exports') {\n reified[i] = exports;\n } else if (deps[i] === 'require') {\n reified[i] = require;\n } else {\n reified[i] = require(deps[i], name);\n }\n }\n\n callback.apply(this, reified);\n\n return exports;\n }\n\n require = function (name) {\n return internalRequire(name, null);\n };\n\n // eslint-disable-next-line no-unused-vars\n define = function (name, deps, callback) {\n registry[name] = { deps: deps, callback: callback };\n };\n\n // setup `require` module\n require['default'] = require;\n\n require.has = function registryHas(moduleName) {\n return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);\n };\n\n require._eak_seen = require.entries = registry;\n})();\n","define(\"@ember/-internals/browser-environment/index\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.hasDOM = _exports.isIE = _exports.isFirefox = _exports.isChrome = _exports.userAgent = _exports.history = _exports.location = _exports.window = void 0;\n // check if window exists and actually is the global\n var hasDom = typeof self === 'object' && self !== null && self.Object === Object && typeof Window !== 'undefined' && self.constructor === Window && typeof document === 'object' && document !== null && self.document === document && typeof location === 'object' && location !== null && self.location === location && typeof history === 'object' && history !== null && self.history === history && typeof navigator === 'object' && navigator !== null && self.navigator === navigator && typeof navigator.userAgent === 'string';\n _exports.hasDOM = hasDom;\n var window = hasDom ? self : null;\n _exports.window = window;\n var location$1 = hasDom ? self.location : null;\n _exports.location = location$1;\n var history$1 = hasDom ? self.history : null;\n _exports.history = history$1;\n var userAgent = hasDom ? self.navigator.userAgent : 'Lynx (textmode)';\n _exports.userAgent = userAgent;\n var isChrome = hasDom ? typeof chrome === 'object' && !(typeof opera === 'object') : false;\n _exports.isChrome = isChrome;\n var isFirefox = hasDom ? typeof InstallTrigger !== 'undefined' : false;\n _exports.isFirefox = isFirefox;\n var isIE = hasDom ? typeof MSInputMethodContext !== 'undefined' && typeof documentMode !== 'undefined' : false;\n _exports.isIE = isIE;\n});","define(\"@ember/-internals/environment/index\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.getLookup = getLookup;\n _exports.setLookup = setLookup;\n _exports.getENV = getENV;\n _exports.ENV = _exports.context = _exports.global = void 0;\n\n // from lodash to catch fake globals\n function checkGlobal(value) {\n return value && value.Object === Object ? value : undefined;\n } // element ids can ruin global miss checks\n\n\n function checkElementIdShadowing(value) {\n return value && value.nodeType === undefined ? value : undefined;\n } // export real global\n\n\n var global$1 = checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) || checkGlobal(typeof self === 'object' && self) || checkGlobal(typeof window === 'object' && window) || typeof mainContext !== 'undefined' && mainContext || // set before strict mode in Ember loader/wrapper\n new Function('return this')(); // eval outside of strict mode\n\n _exports.global = global$1;\n\n var context = function (global, Ember) {\n return Ember === undefined ? {\n imports: global,\n exports: global,\n lookup: global\n } : {\n // import jQuery\n imports: Ember.imports || global,\n // export Ember\n exports: Ember.exports || global,\n // search for Namespaces\n lookup: Ember.lookup || global\n };\n }(global$1, global$1.Ember);\n\n _exports.context = context;\n\n function getLookup() {\n return context.lookup;\n }\n\n function setLookup(value) {\n context.lookup = value;\n }\n /**\n The hash of environment variables used to control various configuration\n settings. To specify your own or override default settings, add the\n desired properties to a global hash named `EmberENV` (or `ENV` for\n backwards compatibility with earlier versions of Ember). The `EmberENV`\n hash must be created before loading Ember.\n \n @class EmberENV\n @type Object\n @public\n */\n\n\n var ENV = {\n ENABLE_OPTIONAL_FEATURES: false,\n\n /**\n Determines whether Ember should add to `Array`\n native object prototypes, a few extra methods in order to provide a more\n friendly API.\n We generally recommend leaving this option set to true however, if you need\n to turn it off, you can add the configuration property\n `EXTEND_PROTOTYPES` to `EmberENV` and set it to `false`.\n Note, when disabled (the default configuration for Ember Addons), you will\n instead have to access all methods and functions from the Ember\n namespace.\n @property EXTEND_PROTOTYPES\n @type Boolean\n @default true\n @for EmberENV\n @public\n */\n EXTEND_PROTOTYPES: {\n Array: true\n },\n\n /**\n The `LOG_STACKTRACE_ON_DEPRECATION` property, when true, tells Ember to log\n a full stack trace during deprecation warnings.\n @property LOG_STACKTRACE_ON_DEPRECATION\n @type Boolean\n @default true\n @for EmberENV\n @public\n */\n LOG_STACKTRACE_ON_DEPRECATION: true,\n\n /**\n The `LOG_VERSION` property, when true, tells Ember to log versions of all\n dependent libraries in use.\n @property LOG_VERSION\n @type Boolean\n @default true\n @for EmberENV\n @public\n */\n LOG_VERSION: true,\n RAISE_ON_DEPRECATION: false,\n STRUCTURED_PROFILE: false,\n\n /**\n Whether to insert a `
` wrapper around the\n application template. See RFC #280.\n This is not intended to be set directly, as the implementation may change in\n the future. Use `@ember/optional-features` instead.\n @property _APPLICATION_TEMPLATE_WRAPPER\n @for EmberENV\n @type Boolean\n @default true\n @private\n */\n _APPLICATION_TEMPLATE_WRAPPER: true,\n\n /**\n Whether to use Glimmer Component semantics (as opposed to the classic \"Curly\"\n components semantics) for template-only components. See RFC #278.\n This is not intended to be set directly, as the implementation may change in\n the future. Use `@ember/optional-features` instead.\n @property _TEMPLATE_ONLY_GLIMMER_COMPONENTS\n @for EmberENV\n @type Boolean\n @default false\n @private\n */\n _TEMPLATE_ONLY_GLIMMER_COMPONENTS: false,\n\n /**\n Whether to perform extra bookkeeping needed to make the `captureRenderTree`\n API work.\n This has to be set before the ember JavaScript code is evaluated. This is\n usually done by setting `window.EmberENV = { _DEBUG_RENDER_TREE: true };`\n before the \"vendor\" `';\n };\n\n return EventedTokenizer;\n }();\n\n _exports.EventedTokenizer = EventedTokenizer;\n\n var Tokenizer =\n /** @class */\n function () {\n function Tokenizer(entityParser, options) {\n if (options === void 0) {\n options = {};\n }\n\n this.options = options;\n this.token = null;\n this.startLine = 1;\n this.startColumn = 0;\n this.tokens = [];\n this.tokenizer = new EventedTokenizer(this, entityParser, options.mode);\n this._currentAttribute = undefined;\n }\n\n Tokenizer.prototype.tokenize = function (input) {\n this.tokens = [];\n this.tokenizer.tokenize(input);\n return this.tokens;\n };\n\n Tokenizer.prototype.tokenizePart = function (input) {\n this.tokens = [];\n this.tokenizer.tokenizePart(input);\n return this.tokens;\n };\n\n Tokenizer.prototype.tokenizeEOF = function () {\n this.tokens = [];\n this.tokenizer.tokenizeEOF();\n return this.tokens[0];\n };\n\n Tokenizer.prototype.reset = function () {\n this.token = null;\n this.startLine = 1;\n this.startColumn = 0;\n };\n\n Tokenizer.prototype.current = function () {\n var token = this.token;\n\n if (token === null) {\n throw new Error('token was unexpectedly null');\n }\n\n if (arguments.length === 0) {\n return token;\n }\n\n for (var i = 0; i < arguments.length; i++) {\n if (token.type === arguments[i]) {\n return token;\n }\n }\n\n throw new Error(\"token type was unexpectedly \" + token.type);\n };\n\n Tokenizer.prototype.push = function (token) {\n this.token = token;\n this.tokens.push(token);\n };\n\n Tokenizer.prototype.currentAttribute = function () {\n return this._currentAttribute;\n };\n\n Tokenizer.prototype.addLocInfo = function () {\n if (this.options.loc) {\n this.current().loc = {\n start: {\n line: this.startLine,\n column: this.startColumn\n },\n end: {\n line: this.tokenizer.line,\n column: this.tokenizer.column\n }\n };\n }\n\n this.startLine = this.tokenizer.line;\n this.startColumn = this.tokenizer.column;\n }; // Data\n\n\n Tokenizer.prototype.beginData = function () {\n this.push({\n type: \"Chars\"\n /* Chars */\n ,\n chars: ''\n });\n };\n\n Tokenizer.prototype.appendToData = function (char) {\n this.current(\"Chars\"\n /* Chars */\n ).chars += char;\n };\n\n Tokenizer.prototype.finishData = function () {\n this.addLocInfo();\n }; // Comment\n\n\n Tokenizer.prototype.beginComment = function () {\n this.push({\n type: \"Comment\"\n /* Comment */\n ,\n chars: ''\n });\n };\n\n Tokenizer.prototype.appendToCommentData = function (char) {\n this.current(\"Comment\"\n /* Comment */\n ).chars += char;\n };\n\n Tokenizer.prototype.finishComment = function () {\n this.addLocInfo();\n }; // Tags - basic\n\n\n Tokenizer.prototype.tagOpen = function () {};\n\n Tokenizer.prototype.beginStartTag = function () {\n this.push({\n type: \"StartTag\"\n /* StartTag */\n ,\n tagName: '',\n attributes: [],\n selfClosing: false\n });\n };\n\n Tokenizer.prototype.beginEndTag = function () {\n this.push({\n type: \"EndTag\"\n /* EndTag */\n ,\n tagName: ''\n });\n };\n\n Tokenizer.prototype.finishTag = function () {\n this.addLocInfo();\n };\n\n Tokenizer.prototype.markTagAsSelfClosing = function () {\n this.current(\"StartTag\"\n /* StartTag */\n ).selfClosing = true;\n }; // Tags - name\n\n\n Tokenizer.prototype.appendToTagName = function (char) {\n this.current(\"StartTag\"\n /* StartTag */\n , \"EndTag\"\n /* EndTag */\n ).tagName += char;\n }; // Tags - attributes\n\n\n Tokenizer.prototype.beginAttribute = function () {\n this._currentAttribute = ['', '', false];\n };\n\n Tokenizer.prototype.appendToAttributeName = function (char) {\n this.currentAttribute()[0] += char;\n };\n\n Tokenizer.prototype.beginAttributeValue = function (isQuoted) {\n this.currentAttribute()[2] = isQuoted;\n };\n\n Tokenizer.prototype.appendToAttributeValue = function (char) {\n this.currentAttribute()[1] += char;\n };\n\n Tokenizer.prototype.finishAttributeValue = function () {\n this.current(\"StartTag\"\n /* StartTag */\n ).attributes.push(this._currentAttribute);\n };\n\n Tokenizer.prototype.reportSyntaxError = function (message) {\n this.current().syntaxError = message;\n };\n\n return Tokenizer;\n }();\n\n _exports.Tokenizer = Tokenizer;\n\n function tokenize(input, options) {\n var tokenizer = new Tokenizer(new EntityParser(namedCharRefs), options);\n return tokenizer.tokenize(input);\n }\n});"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACt3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5pJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACztNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzmFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;","file":"ember-template-compiler.js"} \ No newline at end of file diff --git a/ember-vendored-pr-19806/ember-testing.js b/ember-vendored-pr-19806/ember-testing.js new file mode 100644 index 0000000..2b34a11 --- /dev/null +++ b/ember-vendored-pr-19806/ember-testing.js @@ -0,0 +1,2134 @@ +(function() { +/*! + * @overview Ember - JavaScript Application Framework + * @copyright Copyright 2011-2021 Tilde Inc. and contributors + * Portions Copyright 2006-2011 Strobe Inc. + * Portions Copyright 2008-2011 Apple Inc. All rights reserved. + * @license Licensed under MIT license + * See https://raw.github.com/emberjs/ember.js/master/LICENSE + * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74 + */ +/* eslint-disable no-var */ + +/* globals global globalThis self */ + +/* eslint-disable-next-line no-unused-vars */ +var define, require; + +(function () { + var globalObj = typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : null; + + if (globalObj === null) { + throw new Error('unable to locate global object'); + } + + if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') { + define = globalObj.define; + require = globalObj.require; + return; + } + + var registry = Object.create(null); + var seen = Object.create(null); + + function missingModule(name, referrerName) { + if (referrerName) { + throw new Error('Could not find module ' + name + ' required by: ' + referrerName); + } else { + throw new Error('Could not find module ' + name); + } + } + + function internalRequire(_name, referrerName) { + var name = _name; + var mod = registry[name]; + + if (!mod) { + name = name + '/index'; + mod = registry[name]; + } + + var exports = seen[name]; + + if (exports !== undefined) { + return exports; + } + + exports = seen[name] = {}; + + if (!mod) { + missingModule(_name, referrerName); + } + + var deps = mod.deps; + var callback = mod.callback; + var reified = new Array(deps.length); + + for (var i = 0; i < deps.length; i++) { + if (deps[i] === 'exports') { + reified[i] = exports; + } else if (deps[i] === 'require') { + reified[i] = require; + } else { + reified[i] = require(deps[i], name); + } + } + + callback.apply(this, reified); + return exports; + } + + require = function (name) { + return internalRequire(name, null); + }; // eslint-disable-next-line no-unused-vars + + + define = function (name, deps, callback) { + registry[name] = { + deps: deps, + callback: callback + }; + }; // setup `require` module + + + require['default'] = require; + + require.has = function registryHas(moduleName) { + return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']); + }; + + require._eak_seen = require.entries = registry; +})(); +define("@ember/debug/index", ["exports", "@ember/-internals/browser-environment", "@ember/error", "@ember/debug/lib/deprecate", "@ember/debug/lib/testing", "@ember/debug/lib/warn", "@ember/-internals/utils", "@ember/debug/lib/capture-render-tree"], function (_exports, _browserEnvironment, _error, _deprecate2, _testing, _warn2, _utils, _captureRenderTree) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + Object.defineProperty(_exports, "registerDeprecationHandler", { + enumerable: true, + get: function () { + return _deprecate2.registerHandler; + } + }); + Object.defineProperty(_exports, "isTesting", { + enumerable: true, + get: function () { + return _testing.isTesting; + } + }); + Object.defineProperty(_exports, "setTesting", { + enumerable: true, + get: function () { + return _testing.setTesting; + } + }); + Object.defineProperty(_exports, "registerWarnHandler", { + enumerable: true, + get: function () { + return _warn2.registerHandler; + } + }); + Object.defineProperty(_exports, "inspect", { + enumerable: true, + get: function () { + return _utils.inspect; + } + }); + Object.defineProperty(_exports, "captureRenderTree", { + enumerable: true, + get: function () { + return _captureRenderTree.default; + } + }); + _exports._warnIfUsingStrippedFeatureFlags = _exports.getDebugFunction = _exports.setDebugFunction = _exports.deprecateFunc = _exports.runInDebug = _exports.debugFreeze = _exports.debugSeal = _exports.deprecate = _exports.debug = _exports.warn = _exports.info = _exports.assert = void 0; + + // These are the default production build versions: + var noop = () => {}; + + var assert = noop; + _exports.assert = assert; + var info = noop; + _exports.info = info; + var warn = noop; + _exports.warn = warn; + var debug = noop; + _exports.debug = debug; + var deprecate = noop; + _exports.deprecate = deprecate; + var debugSeal = noop; + _exports.debugSeal = debugSeal; + var debugFreeze = noop; + _exports.debugFreeze = debugFreeze; + var runInDebug = noop; + _exports.runInDebug = runInDebug; + var setDebugFunction = noop; + _exports.setDebugFunction = setDebugFunction; + var getDebugFunction = noop; + _exports.getDebugFunction = getDebugFunction; + + var deprecateFunc = function () { + return arguments[arguments.length - 1]; + }; + + _exports.deprecateFunc = deprecateFunc; + + if (true + /* DEBUG */ + ) { + _exports.setDebugFunction = setDebugFunction = function (type, callback) { + switch (type) { + case 'assert': + return _exports.assert = assert = callback; + + case 'info': + return _exports.info = info = callback; + + case 'warn': + return _exports.warn = warn = callback; + + case 'debug': + return _exports.debug = debug = callback; + + case 'deprecate': + return _exports.deprecate = deprecate = callback; + + case 'debugSeal': + return _exports.debugSeal = debugSeal = callback; + + case 'debugFreeze': + return _exports.debugFreeze = debugFreeze = callback; + + case 'runInDebug': + return _exports.runInDebug = runInDebug = callback; + + case 'deprecateFunc': + return _exports.deprecateFunc = deprecateFunc = callback; + } + }; + + _exports.getDebugFunction = getDebugFunction = function (type) { + switch (type) { + case 'assert': + return assert; + + case 'info': + return info; + + case 'warn': + return warn; + + case 'debug': + return debug; + + case 'deprecate': + return deprecate; + + case 'debugSeal': + return debugSeal; + + case 'debugFreeze': + return debugFreeze; + + case 'runInDebug': + return runInDebug; + + case 'deprecateFunc': + return deprecateFunc; + } + }; + } + /** + @module @ember/debug + */ + + + if (true + /* DEBUG */ + ) { + /** + Verify that a certain expectation is met, or throw a exception otherwise. + This is useful for communicating assumptions in the code to other human + readers as well as catching bugs that accidentally violates these + expectations. + Assertions are removed from production builds, so they can be freely added + for documentation and debugging purposes without worries of incuring any + performance penalty. However, because of that, they should not be used for + checks that could reasonably fail during normal usage. Furthermore, care + should be taken to avoid accidentally relying on side-effects produced from + evaluating the condition itself, since the code will not run in production. + ```javascript + import { assert } from '@ember/debug'; + // Test for truthiness + assert('Must pass a string', typeof str === 'string'); + // Fail unconditionally + assert('This code path should never be run'); + ``` + @method assert + @static + @for @ember/debug + @param {String} description Describes the expectation. This will become the + text of the Error thrown if the assertion fails. + @param {any} condition Must be truthy for the assertion to pass. If + falsy, an exception will be thrown. + @public + @since 1.0.0 + */ + setDebugFunction('assert', function assert(desc, test) { + if (!test) { + throw new _error.default(`Assertion Failed: ${desc}`); + } + }); + /** + Display a debug notice. + Calls to this function are not invoked in production builds. + ```javascript + import { debug } from '@ember/debug'; + debug('I\'m a debug notice!'); + ``` + @method debug + @for @ember/debug + @static + @param {String} message A debug message to display. + @public + */ + + setDebugFunction('debug', function debug(message) { + /* eslint-disable no-console */ + if (console.debug) { + console.debug(`DEBUG: ${message}`); + } else { + console.log(`DEBUG: ${message}`); + } + /* eslint-ensable no-console */ + + }); + /** + Display an info notice. + Calls to this function are removed from production builds, so they can be + freely added for documentation and debugging purposes without worries of + incuring any performance penalty. + @method info + @private + */ + + setDebugFunction('info', function info() { + console.info(...arguments); + /* eslint-disable-line no-console */ + }); + /** + @module @ember/debug + @public + */ + + /** + Alias an old, deprecated method with its new counterpart. + Display a deprecation warning with the provided message and a stack trace + (Chrome and Firefox only) when the assigned method is called. + Calls to this function are removed from production builds, so they can be + freely added for documentation and debugging purposes without worries of + incuring any performance penalty. + ```javascript + import { deprecateFunc } from '@ember/debug'; + Ember.oldMethod = deprecateFunc('Please use the new, updated method', options, Ember.newMethod); + ``` + @method deprecateFunc + @static + @for @ember/debug + @param {String} message A description of the deprecation. + @param {Object} [options] The options object for `deprecate`. + @param {Function} func The new function called to replace its deprecated counterpart. + @return {Function} A new function that wraps the original function with a deprecation warning + @private + */ + + setDebugFunction('deprecateFunc', function deprecateFunc(...args) { + if (args.length === 3) { + var [message, options, func] = args; + return function (...args) { + deprecate(message, false, options); + return func.apply(this, args); + }; + } else { + var [_message, _func] = args; + return function () { + deprecate(_message); + return _func.apply(this, arguments); + }; + } + }); + /** + @module @ember/debug + @public + */ + + /** + Run a function meant for debugging. + Calls to this function are removed from production builds, so they can be + freely added for documentation and debugging purposes without worries of + incuring any performance penalty. + ```javascript + import Component from '@ember/component'; + import { runInDebug } from '@ember/debug'; + runInDebug(() => { + Component.reopen({ + didInsertElement() { + console.log("I'm happy"); + } + }); + }); + ``` + @method runInDebug + @for @ember/debug + @static + @param {Function} func The function to be executed. + @since 1.5.0 + @public + */ + + setDebugFunction('runInDebug', function runInDebug(func) { + func(); + }); + setDebugFunction('debugSeal', function debugSeal(obj) { + Object.seal(obj); + }); + setDebugFunction('debugFreeze', function debugFreeze(obj) { + // re-freezing an already frozen object introduces a significant + // performance penalty on Chrome (tested through 59). + // + // See: https://bugs.chromium.org/p/v8/issues/detail?id=6450 + if (!Object.isFrozen(obj)) { + Object.freeze(obj); + } + }); + setDebugFunction('deprecate', _deprecate2.default); + setDebugFunction('warn', _warn2.default); + } + + var _warnIfUsingStrippedFeatureFlags; + + _exports._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags; + + if (true + /* DEBUG */ + && !(0, _testing.isTesting)()) { + if (typeof window !== 'undefined' && (_browserEnvironment.isFirefox || _browserEnvironment.isChrome) && window.addEventListener) { + window.addEventListener('load', () => { + if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) { + var downloadURL; + + if (_browserEnvironment.isChrome) { + downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi'; + } else if (_browserEnvironment.isFirefox) { + downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/'; + } + + debug(`For more advanced debugging, install the Ember Inspector from ${downloadURL}`); + } + }, false); + } + } +}); +define("@ember/debug/lib/capture-render-tree", ["exports", "@glimmer/util"], function (_exports, _util) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = captureRenderTree; + + /** + @module @ember/debug + */ + + /** + Ember Inspector calls this function to capture the current render tree. + + In production mode, this requires turning on `ENV._DEBUG_RENDER_TREE` + before loading Ember. + + @private + @static + @method captureRenderTree + @for @ember/debug + @param app {ApplicationInstance} An `ApplicationInstance`. + @since 3.14.0 + */ + function captureRenderTree(app) { + var renderer = (0, _util.expect)(app.lookup('renderer:-dom'), `BUG: owner is missing renderer`); + return renderer.debugRenderTree.capture(); + } +}); +define("@ember/debug/lib/deprecate", ["exports", "@ember/-internals/environment", "@ember/debug/index", "@ember/debug/lib/handlers"], function (_exports, _environment, _index, _handlers) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.missingOptionDeprecation = _exports.missingOptionsIdDeprecation = _exports.missingOptionsDeprecation = _exports.registerHandler = _exports.default = void 0; + + /** + @module @ember/debug + @public + */ + + /** + Allows for runtime registration of handler functions that override the default deprecation behavior. + Deprecations are invoked by calls to [@ember/debug/deprecate](/ember/release/classes/@ember%2Fdebug/methods/deprecate?anchor=deprecate). + The following example demonstrates its usage by registering a handler that throws an error if the + message contains the word "should", otherwise defers to the default handler. + + ```javascript + import { registerDeprecationHandler } from '@ember/debug'; + + registerDeprecationHandler((message, options, next) => { + if (message.indexOf('should') !== -1) { + throw new Error(`Deprecation message with should: ${message}`); + } else { + // defer to whatever handler was registered before this one + next(message, options); + } + }); + ``` + + The handler function takes the following arguments: + +
    +
  • message - The message received from the deprecation call.
  • +
  • options - An object passed in with the deprecation call containing additional information including:
  • +
      +
    • id - An id of the deprecation in the form of package-name.specific-deprecation.
    • +
    • until - The Ember version number the feature and deprecation will be removed in.
    • +
    +
  • next - A function that calls into the previously registered handler.
  • +
+ + @public + @static + @method registerDeprecationHandler + @for @ember/debug + @param handler {Function} A function to handle deprecation calls. + @since 2.1.0 + */ + var registerHandler = () => {}; + + _exports.registerHandler = registerHandler; + var missingOptionsDeprecation; + _exports.missingOptionsDeprecation = missingOptionsDeprecation; + var missingOptionsIdDeprecation; + _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation; + + var missingOptionDeprecation = () => ''; + + _exports.missingOptionDeprecation = missingOptionDeprecation; + + var deprecate = () => {}; + + if (true + /* DEBUG */ + ) { + _exports.registerHandler = registerHandler = function registerHandler(handler) { + (0, _handlers.registerHandler)('deprecate', handler); + }; + + var formatMessage = function formatMessage(_message, options) { + var message = _message; + + if (options && options.id) { + message = message + ` [deprecation id: ${options.id}]`; + } + + if (options && options.url) { + message += ` See ${options.url} for more details.`; + } + + return message; + }; + + registerHandler(function logDeprecationToConsole(message, options) { + var updatedMessage = formatMessage(message, options); + console.warn(`DEPRECATION: ${updatedMessage}`); // eslint-disable-line no-console + }); + var captureErrorForStack; + + if (new Error().stack) { + captureErrorForStack = () => new Error(); + } else { + captureErrorForStack = () => { + try { + __fail__.fail(); + } catch (e) { + return e; + } + }; + } + + registerHandler(function logDeprecationStackTrace(message, options, next) { + if (_environment.ENV.LOG_STACKTRACE_ON_DEPRECATION) { + var stackStr = ''; + var error = captureErrorForStack(); + var stack; + + if (error.stack) { + if (error['arguments']) { + // Chrome + stack = error.stack.replace(/^\s+at\s+/gm, '').replace(/^([^(]+?)([\n$])/gm, '{anonymous}($1)$2').replace(/^Object.\s*\(([^)]+)\)/gm, '{anonymous}($1)').split('\n'); + stack.shift(); + } else { + // Firefox + stack = error.stack.replace(/(?:\n@:0)?\s+$/m, '').replace(/^\(/gm, '{anonymous}(').split('\n'); + } + + stackStr = `\n ${stack.slice(2).join('\n ')}`; + } + + var updatedMessage = formatMessage(message, options); + console.warn(`DEPRECATION: ${updatedMessage}${stackStr}`); // eslint-disable-line no-console + } else { + next(message, options); + } + }); + registerHandler(function raiseOnDeprecation(message, options, next) { + if (_environment.ENV.RAISE_ON_DEPRECATION) { + var updatedMessage = formatMessage(message); + throw new Error(updatedMessage); + } else { + next(message, options); + } + }); + _exports.missingOptionsDeprecation = missingOptionsDeprecation = 'When calling `deprecate` you ' + 'must provide an `options` hash as the third parameter. ' + '`options` should include `id` and `until` properties.'; + _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation = 'When calling `deprecate` you must provide `id` in options.'; + + _exports.missingOptionDeprecation = missingOptionDeprecation = (id, missingOption) => { + return `When calling \`deprecate\` you must provide \`${missingOption}\` in options. Missing options.${missingOption} in "${id}" deprecation`; + }; + /** + @module @ember/debug + @public + */ + + /** + Display a deprecation warning with the provided message and a stack trace + (Chrome and Firefox only). + * In a production build, this method is defined as an empty function (NOP). + Uses of this method in Ember itself are stripped from the ember.prod.js build. + @method deprecate + @for @ember/debug + @param {String} message A description of the deprecation. + @param {Boolean} test A boolean. If falsy, the deprecation will be displayed. + @param {Object} options + @param {String} options.id A unique id for this deprecation. The id can be + used by Ember debugging tools to change the behavior (raise, log or silence) + for that specific deprecation. The id should be namespaced by dots, e.g. + "view.helper.select". + @param {string} options.until The version of Ember when this deprecation + warning will be removed. + @param {String} options.for A namespace for the deprecation, usually the package name + @param {Object} options.since Describes when the deprecation became available and enabled. + @param {String} [options.url] An optional url to the transition guide on the + emberjs.com website. + @static + @public + @since 1.0.0 + */ + + + deprecate = function deprecate(message, test, options) { + (0, _index.assert)(missingOptionsDeprecation, Boolean(options && (options.id || options.until))); + (0, _index.assert)(missingOptionsIdDeprecation, Boolean(options.id)); + (0, _index.assert)(missingOptionDeprecation(options.id, 'until'), Boolean(options.until)); + (0, _index.assert)(missingOptionDeprecation(options.id, 'for'), Boolean(options.for)); + (0, _index.assert)(missingOptionDeprecation(options.id, 'since'), Boolean(options.since)); + (0, _handlers.invoke)('deprecate', message, test, options); + }; + } + + var _default = deprecate; + _exports.default = _default; +}); +define("@ember/debug/lib/handlers", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.invoke = _exports.registerHandler = _exports.HANDLERS = void 0; + var HANDLERS = {}; + _exports.HANDLERS = HANDLERS; + + var registerHandler = () => {}; + + _exports.registerHandler = registerHandler; + + var invoke = () => {}; + + _exports.invoke = invoke; + + if (true + /* DEBUG */ + ) { + _exports.registerHandler = registerHandler = function registerHandler(type, callback) { + var nextHandler = HANDLERS[type] || (() => {}); + + HANDLERS[type] = (message, options) => { + callback(message, options, nextHandler); + }; + }; + + _exports.invoke = invoke = function invoke(type, message, test, options) { + if (test) { + return; + } + + var handlerForType = HANDLERS[type]; + + if (handlerForType) { + handlerForType(message, options); + } + }; + } +}); +define("@ember/debug/lib/testing", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.isTesting = isTesting; + _exports.setTesting = setTesting; + var testing = false; + + function isTesting() { + return testing; + } + + function setTesting(value) { + testing = Boolean(value); + } +}); +define("@ember/debug/lib/warn", ["exports", "@ember/debug/index", "@ember/debug/lib/handlers"], function (_exports, _index, _handlers) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.missingOptionsDeprecation = _exports.missingOptionsIdDeprecation = _exports.registerHandler = _exports.default = void 0; + + var registerHandler = () => {}; + + _exports.registerHandler = registerHandler; + + var warn = () => {}; + + var missingOptionsDeprecation; + _exports.missingOptionsDeprecation = missingOptionsDeprecation; + var missingOptionsIdDeprecation; + /** + @module @ember/debug + */ + + _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation; + + if (true + /* DEBUG */ + ) { + /** + Allows for runtime registration of handler functions that override the default warning behavior. + Warnings are invoked by calls made to [@ember/debug/warn](/ember/release/classes/@ember%2Fdebug/methods/warn?anchor=warn). + The following example demonstrates its usage by registering a handler that does nothing overriding Ember's + default warning behavior. + ```javascript + import { registerWarnHandler } from '@ember/debug'; + // next is not called, so no warnings get the default behavior + registerWarnHandler(() => {}); + ``` + The handler function takes the following arguments: +
    +
  • message - The message received from the warn call.
  • +
  • options - An object passed in with the warn call containing additional information including:
  • +
      +
    • id - An id of the warning in the form of package-name.specific-warning.
    • +
    +
  • next - A function that calls into the previously registered handler.
  • +
+ @public + @static + @method registerWarnHandler + @for @ember/debug + @param handler {Function} A function to handle warnings. + @since 2.1.0 + */ + _exports.registerHandler = registerHandler = function registerHandler(handler) { + (0, _handlers.registerHandler)('warn', handler); + }; + + registerHandler(function logWarning(message) { + /* eslint-disable no-console */ + console.warn(`WARNING: ${message}`); + /* eslint-enable no-console */ + }); + _exports.missingOptionsDeprecation = missingOptionsDeprecation = 'When calling `warn` you ' + 'must provide an `options` hash as the third parameter. ' + '`options` should include an `id` property.'; + _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation = 'When calling `warn` you must provide `id` in options.'; + /** + Display a warning with the provided message. + * In a production build, this method is defined as an empty function (NOP). + Uses of this method in Ember itself are stripped from the ember.prod.js build. + ```javascript + import { warn } from '@ember/debug'; + import tomsterCount from './tomster-counter'; // a module in my project + // Log a warning if we have more than 3 tomsters + warn('Too many tomsters!', tomsterCount <= 3, { + id: 'ember-debug.too-many-tomsters' + }); + ``` + @method warn + @for @ember/debug + @static + @param {String} message A warning to display. + @param {Boolean} test An optional boolean. If falsy, the warning + will be displayed. + @param {Object} options An object that can be used to pass a unique + `id` for this warning. The `id` can be used by Ember debugging tools + to change the behavior (raise, log, or silence) for that specific warning. + The `id` should be namespaced by dots, e.g. "ember-debug.feature-flag-with-features-stripped" + @public + @since 1.0.0 + */ + + warn = function warn(message, test, options) { + if (arguments.length === 2 && typeof test === 'object') { + options = test; + test = false; + } + + (0, _index.assert)(missingOptionsDeprecation, Boolean(options)); + (0, _index.assert)(missingOptionsIdDeprecation, Boolean(options && options.id)); + (0, _handlers.invoke)('warn', message, test, options); + }; + } + + var _default = warn; + _exports.default = _default; +}); +define("ember-testing/index", ["exports", "ember-testing/lib/test", "ember-testing/lib/adapters/adapter", "ember-testing/lib/setup_for_testing", "ember-testing/lib/adapters/qunit", "ember-testing/lib/ext/application", "ember-testing/lib/ext/rsvp", "ember-testing/lib/helpers", "ember-testing/lib/initializers"], function (_exports, _test, _adapter, _setup_for_testing, _qunit, _application, _rsvp, _helpers, _initializers) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + Object.defineProperty(_exports, "Test", { + enumerable: true, + get: function () { + return _test.default; + } + }); + Object.defineProperty(_exports, "Adapter", { + enumerable: true, + get: function () { + return _adapter.default; + } + }); + Object.defineProperty(_exports, "setupForTesting", { + enumerable: true, + get: function () { + return _setup_for_testing.default; + } + }); + Object.defineProperty(_exports, "QUnitAdapter", { + enumerable: true, + get: function () { + return _qunit.default; + } + }); +}); +define("ember-testing/lib/adapters/adapter", ["exports", "@ember/-internals/runtime"], function (_exports, _runtime) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + function K() { + return this; + } + /** + @module @ember/test + */ + + /** + The primary purpose of this class is to create hooks that can be implemented + by an adapter for various test frameworks. + + @class TestAdapter + @public + */ + + + var _default = _runtime.Object.extend({ + /** + This callback will be called whenever an async operation is about to start. + Override this to call your framework's methods that handle async + operations. + @public + @method asyncStart + */ + asyncStart: K, + + /** + This callback will be called whenever an async operation has completed. + @public + @method asyncEnd + */ + asyncEnd: K, + + /** + Override this method with your testing framework's false assertion. + This function is called whenever an exception occurs causing the testing + promise to fail. + QUnit example: + ```javascript + exception: function(error) { + ok(false, error); + }; + ``` + @public + @method exception + @param {String} error The exception to be raised. + */ + exception(error) { + throw error; + } + + }); + + _exports.default = _default; +}); +define("ember-testing/lib/adapters/qunit", ["exports", "@ember/-internals/utils", "ember-testing/lib/adapters/adapter"], function (_exports, _utils, _adapter) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + /* globals QUnit */ + + /** + @module ember + */ + + /** + This class implements the methods defined by TestAdapter for the + QUnit testing framework. + + @class QUnitAdapter + @namespace Ember.Test + @extends TestAdapter + @public + */ + var _default = _adapter.default.extend({ + init() { + this.doneCallbacks = []; + }, + + asyncStart() { + if (typeof QUnit.stop === 'function') { + // very old QUnit version + // eslint-disable-next-line qunit/no-qunit-stop + QUnit.stop(); + } else { + this.doneCallbacks.push(QUnit.config.current ? QUnit.config.current.assert.async() : null); + } + }, + + asyncEnd() { + // checking for QUnit.stop here (even though we _need_ QUnit.start) because + // QUnit.start() still exists in QUnit 2.x (it just throws an error when calling + // inside a test context) + if (typeof QUnit.stop === 'function') { + QUnit.start(); + } else { + var done = this.doneCallbacks.pop(); // This can be null if asyncStart() was called outside of a test + + if (done) { + done(); + } + } + }, + + exception(error) { + QUnit.config.current.assert.ok(false, (0, _utils.inspect)(error)); + } + + }); + + _exports.default = _default; +}); +define("ember-testing/lib/ext/application", ["@ember/application", "ember-testing/lib/setup_for_testing", "ember-testing/lib/test/helpers", "ember-testing/lib/test/promise", "ember-testing/lib/test/run", "ember-testing/lib/test/on_inject_helpers", "ember-testing/lib/test/adapter"], function (_application, _setup_for_testing, _helpers, _promise, _run, _on_inject_helpers, _adapter) { + "use strict"; + + _application.default.reopen({ + /** + This property contains the testing helpers for the current application. These + are created once you call `injectTestHelpers` on your `Application` + instance. The included helpers are also available on the `window` object by + default, but can be used from this object on the individual application also. + @property testHelpers + @type {Object} + @default {} + @public + */ + testHelpers: {}, + + /** + This property will contain the original methods that were registered + on the `helperContainer` before `injectTestHelpers` is called. + When `removeTestHelpers` is called, these methods are restored to the + `helperContainer`. + @property originalMethods + @type {Object} + @default {} + @private + @since 1.3.0 + */ + originalMethods: {}, + + /** + This property indicates whether or not this application is currently in + testing mode. This is set when `setupForTesting` is called on the current + application. + @property testing + @type {Boolean} + @default false + @since 1.3.0 + @public + */ + testing: false, + + /** + This hook defers the readiness of the application, so that you can start + the app when your tests are ready to run. It also sets the router's + location to 'none', so that the window's location will not be modified + (preventing both accidental leaking of state between tests and interference + with your testing framework). `setupForTesting` should only be called after + setting a custom `router` class (for example `App.Router = Router.extend(`). + Example: + ``` + App.setupForTesting(); + ``` + @method setupForTesting + @public + */ + setupForTesting() { + (0, _setup_for_testing.default)(); + this.testing = true; + this.resolveRegistration('router:main').reopen({ + location: 'none' + }); + }, + + /** + This will be used as the container to inject the test helpers into. By + default the helpers are injected into `window`. + @property helperContainer + @type {Object} The object to be used for test helpers. + @default window + @since 1.2.0 + @private + */ + helperContainer: null, + + /** + This injects the test helpers into the `helperContainer` object. If an object is provided + it will be used as the helperContainer. If `helperContainer` is not set it will default + to `window`. If a function of the same name has already been defined it will be cached + (so that it can be reset if the helper is removed with `unregisterHelper` or + `removeTestHelpers`). + Any callbacks registered with `onInjectHelpers` will be called once the + helpers have been injected. + Example: + ``` + App.injectTestHelpers(); + ``` + @method injectTestHelpers + @public + */ + injectTestHelpers(helperContainer) { + if (helperContainer) { + this.helperContainer = helperContainer; + } else { + this.helperContainer = window; + } + + this.reopen({ + willDestroy() { + this._super(...arguments); + + this.removeTestHelpers(); + } + + }); + this.testHelpers = {}; + + for (var name in _helpers.helpers) { + this.originalMethods[name] = this.helperContainer[name]; + this.testHelpers[name] = this.helperContainer[name] = helper(this, name); + protoWrap(_promise.default.prototype, name, helper(this, name), _helpers.helpers[name].meta.wait); + } + + (0, _on_inject_helpers.invokeInjectHelpersCallbacks)(this); + }, + + /** + This removes all helpers that have been registered, and resets and functions + that were overridden by the helpers. + Example: + ```javascript + App.removeTestHelpers(); + ``` + @public + @method removeTestHelpers + */ + removeTestHelpers() { + if (!this.helperContainer) { + return; + } + + for (var name in _helpers.helpers) { + this.helperContainer[name] = this.originalMethods[name]; + delete _promise.default.prototype[name]; + delete this.testHelpers[name]; + delete this.originalMethods[name]; + } + } + + }); // This method is no longer needed + // But still here for backwards compatibility + // of helper chaining + + + function protoWrap(proto, name, callback, isAsync) { + proto[name] = function (...args) { + if (isAsync) { + return callback.apply(this, args); + } else { + return this.then(function () { + return callback.apply(this, args); + }); + } + }; + } + + function helper(app, name) { + var fn = _helpers.helpers[name].method; + var meta = _helpers.helpers[name].meta; + + if (!meta.wait) { + return (...args) => fn.apply(app, [app, ...args]); + } + + return (...args) => { + var lastPromise = (0, _run.default)(() => (0, _promise.resolve)((0, _promise.getLastPromise)())); // wait for last helper's promise to resolve and then + // execute. To be safe, we need to tell the adapter we're going + // asynchronous here, because fn may not be invoked before we + // return. + + (0, _adapter.asyncStart)(); + return lastPromise.then(() => fn.apply(app, [app, ...args])).finally(_adapter.asyncEnd); + }; + } +}); +define("ember-testing/lib/ext/rsvp", ["exports", "@ember/-internals/runtime", "@ember/runloop", "@ember/debug", "ember-testing/lib/test/adapter"], function (_exports, _runtime, _runloop, _debug, _adapter) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + _runtime.RSVP.configure('async', function (callback, promise) { + // if schedule will cause autorun, we need to inform adapter + if ((0, _debug.isTesting)() && !_runloop._backburner.currentInstance) { + (0, _adapter.asyncStart)(); + + _runloop._backburner.schedule('actions', () => { + (0, _adapter.asyncEnd)(); + callback(promise); + }); + } else { + _runloop._backburner.schedule('actions', () => callback(promise)); + } + }); + + var _default = _runtime.RSVP; + _exports.default = _default; +}); +define("ember-testing/lib/helpers", ["ember-testing/lib/test/helpers", "ember-testing/lib/helpers/and_then", "ember-testing/lib/helpers/current_path", "ember-testing/lib/helpers/current_route_name", "ember-testing/lib/helpers/current_url", "ember-testing/lib/helpers/pause_test", "ember-testing/lib/helpers/visit", "ember-testing/lib/helpers/wait"], function (_helpers, _and_then, _current_path, _current_route_name, _current_url, _pause_test, _visit, _wait) { + "use strict"; + + (0, _helpers.registerAsyncHelper)('visit', _visit.default); + (0, _helpers.registerAsyncHelper)('wait', _wait.default); + (0, _helpers.registerAsyncHelper)('andThen', _and_then.default); + (0, _helpers.registerAsyncHelper)('pauseTest', _pause_test.pauseTest); + (0, _helpers.registerHelper)('currentRouteName', _current_route_name.default); + (0, _helpers.registerHelper)('currentPath', _current_path.default); + (0, _helpers.registerHelper)('currentURL', _current_url.default); + (0, _helpers.registerHelper)('resumeTest', _pause_test.resumeTest); +}); +define("ember-testing/lib/helpers/and_then", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = andThen; + + function andThen(app, callback) { + return app.testHelpers.wait(callback(app)); + } +}); +define("ember-testing/lib/helpers/current_path", ["exports", "@ember/-internals/metal"], function (_exports, _metal) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = currentPath; + + /** + @module ember + */ + + /** + Returns the current path. + + Example: + + ```javascript + function validateURL() { + equal(currentPath(), 'some.path.index', "correct path was transitioned into."); + } + + click('#some-link-id').then(validateURL); + ``` + + @method currentPath + @return {Object} The currently active path. + @since 1.5.0 + @public + */ + function currentPath(app) { + var routingService = app.__container__.lookup('service:-routing'); + + return (0, _metal.get)(routingService, 'currentPath'); + } +}); +define("ember-testing/lib/helpers/current_route_name", ["exports", "@ember/-internals/metal"], function (_exports, _metal) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = currentRouteName; + + /** + @module ember + */ + + /** + Returns the currently active route name. + + Example: + + ```javascript + function validateRouteName() { + equal(currentRouteName(), 'some.path', "correct route was transitioned into."); + } + visit('/some/path').then(validateRouteName) + ``` + + @method currentRouteName + @return {Object} The name of the currently active route. + @since 1.5.0 + @public + */ + function currentRouteName(app) { + var routingService = app.__container__.lookup('service:-routing'); + + return (0, _metal.get)(routingService, 'currentRouteName'); + } +}); +define("ember-testing/lib/helpers/current_url", ["exports", "@ember/-internals/metal"], function (_exports, _metal) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = currentURL; + + /** + @module ember + */ + + /** + Returns the current URL. + + Example: + + ```javascript + function validateURL() { + equal(currentURL(), '/some/path', "correct URL was transitioned into."); + } + + click('#some-link-id').then(validateURL); + ``` + + @method currentURL + @return {Object} The currently active URL. + @since 1.5.0 + @public + */ + function currentURL(app) { + var router = app.__container__.lookup('router:main'); + + return (0, _metal.get)(router, 'location').getURL(); + } +}); +define("ember-testing/lib/helpers/pause_test", ["exports", "@ember/-internals/runtime", "@ember/debug"], function (_exports, _runtime, _debug) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.resumeTest = resumeTest; + _exports.pauseTest = pauseTest; + + /** + @module ember + */ + var resume; + /** + Resumes a test paused by `pauseTest`. + + @method resumeTest + @return {void} + @public + */ + + function resumeTest() { + (true && !(resume) && (0, _debug.assert)('Testing has not been paused. There is nothing to resume.', resume)); + resume(); + resume = undefined; + } + /** + Pauses the current test - this is useful for debugging while testing or for test-driving. + It allows you to inspect the state of your application at any point. + Example (The test will pause before clicking the button): + + ```javascript + visit('/') + return pauseTest(); + click('.btn'); + ``` + + You may want to turn off the timeout before pausing. + + qunit (timeout available to use as of 2.4.0): + + ``` + visit('/'); + assert.timeout(0); + return pauseTest(); + click('.btn'); + ``` + + mocha (timeout happens automatically as of ember-mocha v0.14.0): + + ``` + visit('/'); + this.timeout(0); + return pauseTest(); + click('.btn'); + ``` + + + @since 1.9.0 + @method pauseTest + @return {Object} A promise that will never resolve + @public + */ + + + function pauseTest() { + (0, _debug.info)('Testing paused. Use `resumeTest()` to continue.'); + return new _runtime.RSVP.Promise(resolve => { + resume = resolve; + }, 'TestAdapter paused promise'); + } +}); +define("ember-testing/lib/helpers/visit", ["exports", "@ember/runloop"], function (_exports, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = visit; + + /** + Loads a route, sets up any controllers, and renders any templates associated + with the route as though a real user had triggered the route change while + using your app. + + Example: + + ```javascript + visit('posts/index').then(function() { + // assert something + }); + ``` + + @method visit + @param {String} url the name of the route + @return {RSVP.Promise} + @public + */ + function visit(app, url) { + var router = app.__container__.lookup('router:main'); + + var shouldHandleURL = false; + app.boot().then(() => { + router.location.setURL(url); + + if (shouldHandleURL) { + (0, _runloop.run)(app.__deprecatedInstance__, 'handleURL', url); + } + }); + + if (app._readinessDeferrals > 0) { + router.initialURL = url; + (0, _runloop.run)(app, 'advanceReadiness'); + delete router.initialURL; + } else { + shouldHandleURL = true; + } + + return app.testHelpers.wait(); + } +}); +define("ember-testing/lib/helpers/wait", ["exports", "ember-testing/lib/test/waiters", "@ember/-internals/runtime", "@ember/runloop", "ember-testing/lib/test/pending_requests"], function (_exports, _waiters, _runtime, _runloop, _pending_requests) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = wait; + + /** + @module ember + */ + + /** + Causes the run loop to process any pending events. This is used to ensure that + any async operations from other helpers (or your assertions) have been processed. + + This is most often used as the return value for the helper functions (see 'click', + 'fillIn','visit',etc). However, there is a method to register a test helper which + utilizes this method without the need to actually call `wait()` in your helpers. + + The `wait` helper is built into `registerAsyncHelper` by default. You will not need + to `return app.testHelpers.wait();` - the wait behavior is provided for you. + + Example: + + ```javascript + import { registerAsyncHelper } from '@ember/test'; + + registerAsyncHelper('loginUser', function(app, username, password) { + visit('secured/path/here') + .fillIn('#username', username) + .fillIn('#password', password) + .click('.submit'); + }); + ``` + + @method wait + @param {Object} value The value to be returned. + @return {RSVP.Promise} Promise that resolves to the passed value. + @public + @since 1.0.0 + */ + function wait(app, value) { + return new _runtime.RSVP.Promise(function (resolve) { + var router = app.__container__.lookup('router:main'); // Every 10ms, poll for the async thing to have finished + + + var watcher = setInterval(() => { + // 1. If the router is loading, keep polling + var routerIsLoading = router._routerMicrolib && Boolean(router._routerMicrolib.activeTransition); + + if (routerIsLoading) { + return; + } // 2. If there are pending Ajax requests, keep polling + + + if ((0, _pending_requests.pendingRequests)()) { + return; + } // 3. If there are scheduled timers or we are inside of a run loop, keep polling + + + if ((0, _runloop._hasScheduledTimers)() || (0, _runloop._getCurrentRunLoop)()) { + return; + } + + if ((0, _waiters.checkWaiters)()) { + return; + } // Stop polling + + + clearInterval(watcher); // Synchronously resolve the promise + + (0, _runloop.run)(null, resolve, value); + }, 10); + }); + } +}); +define("ember-testing/lib/initializers", ["@ember/application"], function (_application) { + "use strict"; + + var name = 'deferReadiness in `testing` mode'; + (0, _application.onLoad)('Ember.Application', function (Application) { + if (!Application.initializers[name]) { + Application.initializer({ + name: name, + + initialize(application) { + if (application.testing) { + application.deferReadiness(); + } + } + + }); + } + }); +}); +define("ember-testing/lib/setup_for_testing", ["exports", "@ember/debug", "ember-testing/lib/test/adapter", "ember-testing/lib/adapters/adapter", "ember-testing/lib/adapters/qunit"], function (_exports, _debug, _adapter, _adapter2, _qunit) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = setupForTesting; + + /* global self */ + + /** + Sets Ember up for testing. This is useful to perform + basic setup steps in order to unit test. + + Use `App.setupForTesting` to perform integration tests (full + application testing). + + @method setupForTesting + @namespace Ember + @since 1.5.0 + @private + */ + function setupForTesting() { + (0, _debug.setTesting)(true); + var adapter = (0, _adapter.getAdapter)(); // if adapter is not manually set default to QUnit + + if (!adapter) { + (0, _adapter.setAdapter)(typeof self.QUnit === 'undefined' ? _adapter2.default.create() : _qunit.default.create()); + } + } +}); +define("ember-testing/lib/test", ["exports", "ember-testing/lib/test/helpers", "ember-testing/lib/test/on_inject_helpers", "ember-testing/lib/test/promise", "ember-testing/lib/test/waiters", "ember-testing/lib/test/adapter"], function (_exports, _helpers, _on_inject_helpers, _promise, _waiters, _adapter) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + /** + @module ember + */ + + /** + This is a container for an assortment of testing related functionality: + + * Choose your default test adapter (for your framework of choice). + * Register/Unregister additional test helpers. + * Setup callbacks to be fired when the test helpers are injected into + your application. + + @class Test + @namespace Ember + @public + */ + var Test = { + /** + Hash containing all known test helpers. + @property _helpers + @private + @since 1.7.0 + */ + _helpers: _helpers.helpers, + registerHelper: _helpers.registerHelper, + registerAsyncHelper: _helpers.registerAsyncHelper, + unregisterHelper: _helpers.unregisterHelper, + onInjectHelpers: _on_inject_helpers.onInjectHelpers, + Promise: _promise.default, + promise: _promise.promise, + resolve: _promise.resolve, + registerWaiter: _waiters.registerWaiter, + unregisterWaiter: _waiters.unregisterWaiter, + checkWaiters: _waiters.checkWaiters + }; + /** + Used to allow ember-testing to communicate with a specific testing + framework. + + You can manually set it before calling `App.setupForTesting()`. + + Example: + + ```javascript + Ember.Test.adapter = MyCustomAdapter.create() + ``` + + If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`. + + @public + @for Ember.Test + @property adapter + @type {Class} The adapter to be used. + @default Ember.Test.QUnitAdapter + */ + + Object.defineProperty(Test, 'adapter', { + get: _adapter.getAdapter, + set: _adapter.setAdapter + }); + var _default = Test; + _exports.default = _default; +}); +define("ember-testing/lib/test/adapter", ["exports", "@ember/-internals/error-handling"], function (_exports, _errorHandling) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.getAdapter = getAdapter; + _exports.setAdapter = setAdapter; + _exports.asyncStart = asyncStart; + _exports.asyncEnd = asyncEnd; + var adapter; + + function getAdapter() { + return adapter; + } + + function setAdapter(value) { + adapter = value; + + if (value && typeof value.exception === 'function') { + (0, _errorHandling.setDispatchOverride)(adapterDispatch); + } else { + (0, _errorHandling.setDispatchOverride)(null); + } + } + + function asyncStart() { + if (adapter) { + adapter.asyncStart(); + } + } + + function asyncEnd() { + if (adapter) { + adapter.asyncEnd(); + } + } + + function adapterDispatch(error) { + adapter.exception(error); + console.error(error.stack); // eslint-disable-line no-console + } +}); +define("ember-testing/lib/test/helpers", ["exports", "ember-testing/lib/test/promise"], function (_exports, _promise) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.registerHelper = registerHelper; + _exports.registerAsyncHelper = registerAsyncHelper; + _exports.unregisterHelper = unregisterHelper; + _exports.helpers = void 0; + var helpers = {}; + /** + @module @ember/test + */ + + /** + `registerHelper` is used to register a test helper that will be injected + when `App.injectTestHelpers` is called. + + The helper method will always be called with the current Application as + the first parameter. + + For example: + + ```javascript + import { registerHelper } from '@ember/test'; + import { run } from '@ember/runloop'; + + registerHelper('boot', function(app) { + run(app, app.advanceReadiness); + }); + ``` + + This helper can later be called without arguments because it will be + called with `app` as the first parameter. + + ```javascript + import Application from '@ember/application'; + + App = Application.create(); + App.injectTestHelpers(); + boot(); + ``` + + @public + @for @ember/test + @static + @method registerHelper + @param {String} name The name of the helper method to add. + @param {Function} helperMethod + @param options {Object} + */ + + _exports.helpers = helpers; + + function registerHelper(name, helperMethod) { + helpers[name] = { + method: helperMethod, + meta: { + wait: false + } + }; + } + /** + `registerAsyncHelper` is used to register an async test helper that will be injected + when `App.injectTestHelpers` is called. + + The helper method will always be called with the current Application as + the first parameter. + + For example: + + ```javascript + import { registerAsyncHelper } from '@ember/test'; + import { run } from '@ember/runloop'; + + registerAsyncHelper('boot', function(app) { + run(app, app.advanceReadiness); + }); + ``` + + The advantage of an async helper is that it will not run + until the last async helper has completed. All async helpers + after it will wait for it complete before running. + + + For example: + + ```javascript + import { registerAsyncHelper } from '@ember/test'; + + registerAsyncHelper('deletePost', function(app, postId) { + click('.delete-' + postId); + }); + + // ... in your test + visit('/post/2'); + deletePost(2); + visit('/post/3'); + deletePost(3); + ``` + + @public + @for @ember/test + @method registerAsyncHelper + @param {String} name The name of the helper method to add. + @param {Function} helperMethod + @since 1.2.0 + */ + + + function registerAsyncHelper(name, helperMethod) { + helpers[name] = { + method: helperMethod, + meta: { + wait: true + } + }; + } + /** + Remove a previously added helper method. + + Example: + + ```javascript + import { unregisterHelper } from '@ember/test'; + + unregisterHelper('wait'); + ``` + + @public + @method unregisterHelper + @static + @for @ember/test + @param {String} name The helper to remove. + */ + + + function unregisterHelper(name) { + delete helpers[name]; + delete _promise.default.prototype[name]; + } +}); +define("ember-testing/lib/test/on_inject_helpers", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.onInjectHelpers = onInjectHelpers; + _exports.invokeInjectHelpersCallbacks = invokeInjectHelpersCallbacks; + _exports.callbacks = void 0; + var callbacks = []; + /** + Used to register callbacks to be fired whenever `App.injectTestHelpers` + is called. + + The callback will receive the current application as an argument. + + Example: + + ```javascript + import $ from 'jquery'; + + Ember.Test.onInjectHelpers(function() { + $(document).ajaxSend(function() { + Test.pendingRequests++; + }); + + $(document).ajaxComplete(function() { + Test.pendingRequests--; + }); + }); + ``` + + @public + @for Ember.Test + @method onInjectHelpers + @param {Function} callback The function to be called. + */ + + _exports.callbacks = callbacks; + + function onInjectHelpers(callback) { + callbacks.push(callback); + } + + function invokeInjectHelpersCallbacks(app) { + for (var i = 0; i < callbacks.length; i++) { + callbacks[i](app); + } + } +}); +define("ember-testing/lib/test/pending_requests", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.pendingRequests = pendingRequests; + _exports.clearPendingRequests = clearPendingRequests; + _exports.incrementPendingRequests = incrementPendingRequests; + _exports.decrementPendingRequests = decrementPendingRequests; + var requests = []; + + function pendingRequests() { + return requests.length; + } + + function clearPendingRequests() { + requests.length = 0; + } + + function incrementPendingRequests(_, xhr) { + requests.push(xhr); + } + + function decrementPendingRequests(_, xhr) { + setTimeout(function () { + for (var i = 0; i < requests.length; i++) { + if (xhr === requests[i]) { + requests.splice(i, 1); + break; + } + } + }, 0); + } +}); +define("ember-testing/lib/test/promise", ["exports", "@ember/-internals/runtime", "ember-testing/lib/test/run"], function (_exports, _runtime, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.promise = promise; + _exports.resolve = resolve; + _exports.getLastPromise = getLastPromise; + _exports.default = void 0; + var lastPromise; + + class TestPromise extends _runtime.RSVP.Promise { + constructor() { + super(...arguments); + lastPromise = this; + } + + then(_onFulfillment, ...args) { + var onFulfillment = typeof _onFulfillment === 'function' ? result => isolate(_onFulfillment, result) : undefined; + return super.then(onFulfillment, ...args); + } + + } + /** + This returns a thenable tailored for testing. It catches failed + `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception` + callback in the last chained then. + + This method should be returned by async helpers such as `wait`. + + @public + @for Ember.Test + @method promise + @param {Function} resolver The function used to resolve the promise. + @param {String} label An optional string for identifying the promise. + */ + + + _exports.default = TestPromise; + + function promise(resolver, label) { + var fullLabel = `Ember.Test.promise: ${label || ''}`; + return new TestPromise(resolver, fullLabel); + } + /** + Replacement for `Ember.RSVP.resolve` + The only difference is this uses + an instance of `Ember.Test.Promise` + + @public + @for Ember.Test + @method resolve + @param {Mixed} The value to resolve + @since 1.2.0 + */ + + + function resolve(result, label) { + return TestPromise.resolve(result, label); + } + + function getLastPromise() { + return lastPromise; + } // This method isolates nested async methods + // so that they don't conflict with other last promises. + // + // 1. Set `Ember.Test.lastPromise` to null + // 2. Invoke method + // 3. Return the last promise created during method + + + function isolate(onFulfillment, result) { + // Reset lastPromise for nested helpers + lastPromise = null; + var value = onFulfillment(result); + var promise = lastPromise; + lastPromise = null; // If the method returned a promise + // return that promise. If not, + // return the last async helper's promise + + if (value && value instanceof TestPromise || !promise) { + return value; + } else { + return (0, _run.default)(() => resolve(promise).then(() => value)); + } + } +}); +define("ember-testing/lib/test/run", ["exports", "@ember/runloop"], function (_exports, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = run; + + function run(fn) { + if (!(0, _runloop._getCurrentRunLoop)()) { + return (0, _runloop.run)(fn); + } else { + return fn(); + } + } +}); +define("ember-testing/lib/test/waiters", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.registerWaiter = registerWaiter; + _exports.unregisterWaiter = unregisterWaiter; + _exports.checkWaiters = checkWaiters; + + /** + @module @ember/test + */ + var contexts = []; + var callbacks = []; + /** + This allows ember-testing to play nicely with other asynchronous + events, such as an application that is waiting for a CSS3 + transition or an IndexDB transaction. The waiter runs periodically + after each async helper (i.e. `click`, `andThen`, `visit`, etc) has executed, + until the returning result is truthy. After the waiters finish, the next async helper + is executed and the process repeats. + + For example: + + ```javascript + import { registerWaiter } from '@ember/test'; + + registerWaiter(function() { + return myPendingTransactions() === 0; + }); + ``` + The `context` argument allows you to optionally specify the `this` + with which your callback will be invoked. + + For example: + + ```javascript + import { registerWaiter } from '@ember/test'; + + registerWaiter(MyDB, MyDB.hasPendingTransactions); + ``` + + @public + @for @ember/test + @static + @method registerWaiter + @param {Object} context (optional) + @param {Function} callback + @since 1.2.0 + */ + + function registerWaiter(context, callback) { + if (arguments.length === 1) { + callback = context; + context = null; + } + + if (indexOf(context, callback) > -1) { + return; + } + + contexts.push(context); + callbacks.push(callback); + } + /** + `unregisterWaiter` is used to unregister a callback that was + registered with `registerWaiter`. + + @public + @for @ember/test + @static + @method unregisterWaiter + @param {Object} context (optional) + @param {Function} callback + @since 1.2.0 + */ + + + function unregisterWaiter(context, callback) { + if (!callbacks.length) { + return; + } + + if (arguments.length === 1) { + callback = context; + context = null; + } + + var i = indexOf(context, callback); + + if (i === -1) { + return; + } + + contexts.splice(i, 1); + callbacks.splice(i, 1); + } + /** + Iterates through each registered test waiter, and invokes + its callback. If any waiter returns false, this method will return + true indicating that the waiters have not settled yet. + + This is generally used internally from the acceptance/integration test + infrastructure. + + @public + @for @ember/test + @static + @method checkWaiters + */ + + + function checkWaiters() { + if (!callbacks.length) { + return false; + } + + for (var i = 0; i < callbacks.length; i++) { + var context = contexts[i]; + var callback = callbacks[i]; + + if (!callback.call(context)) { + return true; + } + } + + return false; + } + + function indexOf(context, callback) { + for (var i = 0; i < callbacks.length; i++) { + if (callbacks[i] === callback && contexts[i] === context) { + return i; + } + } + + return -1; + } +}); +require('ember-testing'); +}()); +//# sourceMappingURL=ember-testing.map diff --git a/ember-vendored-pr-19806/ember-testing.map b/ember-vendored-pr-19806/ember-testing.map new file mode 100644 index 0000000..223c9cf --- /dev/null +++ b/ember-vendored-pr-19806/ember-testing.map @@ -0,0 +1 @@ +{"version":3,"sources":["license.js","loader.js","@ember/debug/index.js","@ember/debug/lib/capture-render-tree.js","@ember/debug/lib/deprecate.js","@ember/debug/lib/handlers.js","@ember/debug/lib/testing.js","@ember/debug/lib/warn.js","ember-testing/index.js","ember-testing/lib/adapters/adapter.js","ember-testing/lib/adapters/qunit.js","ember-testing/lib/ext/application.js","ember-testing/lib/ext/rsvp.js","ember-testing/lib/helpers.js","ember-testing/lib/helpers/and_then.js","ember-testing/lib/helpers/current_path.js","ember-testing/lib/helpers/current_route_name.js","ember-testing/lib/helpers/current_url.js","ember-testing/lib/helpers/pause_test.js","ember-testing/lib/helpers/visit.js","ember-testing/lib/helpers/wait.js","ember-testing/lib/initializers.js","ember-testing/lib/setup_for_testing.js","ember-testing/lib/test.js","ember-testing/lib/test/adapter.js","ember-testing/lib/test/helpers.js","ember-testing/lib/test/on_inject_helpers.js","ember-testing/lib/test/pending_requests.js","ember-testing/lib/test/promise.js","ember-testing/lib/test/run.js","ember-testing/lib/test/waiters.js"],"sourcesContent":["/*!\n * @overview Ember - JavaScript Application Framework\n * @copyright Copyright 2011-2021 Tilde Inc. and contributors\n * Portions Copyright 2006-2011 Strobe Inc.\n * Portions Copyright 2008-2011 Apple Inc. All rights reserved.\n * @license Licensed under MIT license\n * See https://raw.github.com/emberjs/ember.js/master/LICENSE\n * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74\n */","/* eslint-disable no-var */\n\n/* globals global globalThis self */\n\n/* eslint-disable-next-line no-unused-vars */\nvar define, require;\n\n(function () {\n var globalObj = typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : null;\n\n if (globalObj === null) {\n throw new Error('unable to locate global object');\n }\n\n if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') {\n define = globalObj.define;\n require = globalObj.require;\n return;\n }\n\n var registry = Object.create(null);\n var seen = Object.create(null);\n\n function missingModule(name, referrerName) {\n if (referrerName) {\n throw new Error('Could not find module ' + name + ' required by: ' + referrerName);\n } else {\n throw new Error('Could not find module ' + name);\n }\n }\n\n function internalRequire(_name, referrerName) {\n var name = _name;\n var mod = registry[name];\n\n if (!mod) {\n name = name + '/index';\n mod = registry[name];\n }\n\n var exports = seen[name];\n\n if (exports !== undefined) {\n return exports;\n }\n\n exports = seen[name] = {};\n\n if (!mod) {\n missingModule(_name, referrerName);\n }\n\n var deps = mod.deps;\n var callback = mod.callback;\n var reified = new Array(deps.length);\n\n for (var i = 0; i < deps.length; i++) {\n if (deps[i] === 'exports') {\n reified[i] = exports;\n } else if (deps[i] === 'require') {\n reified[i] = require;\n } else {\n reified[i] = require(deps[i], name);\n }\n }\n\n callback.apply(this, reified);\n return exports;\n }\n\n require = function (name) {\n return internalRequire(name, null);\n }; // eslint-disable-next-line no-unused-vars\n\n\n define = function (name, deps, callback) {\n registry[name] = {\n deps: deps,\n callback: callback\n };\n }; // setup `require` module\n\n\n require['default'] = require;\n\n require.has = function registryHas(moduleName) {\n return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);\n };\n\n require._eak_seen = require.entries = registry;\n})();","define(\"@ember/debug/index\", [\"exports\", \"@ember/-internals/browser-environment\", \"@ember/error\", \"@ember/debug/lib/deprecate\", \"@ember/debug/lib/testing\", \"@ember/debug/lib/warn\", \"@ember/-internals/utils\", \"@ember/debug/lib/capture-render-tree\"], function (_exports, _browserEnvironment, _error, _deprecate2, _testing, _warn2, _utils, _captureRenderTree) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"registerDeprecationHandler\", {\n enumerable: true,\n get: function () {\n return _deprecate2.registerHandler;\n }\n });\n Object.defineProperty(_exports, \"isTesting\", {\n enumerable: true,\n get: function () {\n return _testing.isTesting;\n }\n });\n Object.defineProperty(_exports, \"setTesting\", {\n enumerable: true,\n get: function () {\n return _testing.setTesting;\n }\n });\n Object.defineProperty(_exports, \"registerWarnHandler\", {\n enumerable: true,\n get: function () {\n return _warn2.registerHandler;\n }\n });\n Object.defineProperty(_exports, \"inspect\", {\n enumerable: true,\n get: function () {\n return _utils.inspect;\n }\n });\n Object.defineProperty(_exports, \"captureRenderTree\", {\n enumerable: true,\n get: function () {\n return _captureRenderTree.default;\n }\n });\n _exports._warnIfUsingStrippedFeatureFlags = _exports.getDebugFunction = _exports.setDebugFunction = _exports.deprecateFunc = _exports.runInDebug = _exports.debugFreeze = _exports.debugSeal = _exports.deprecate = _exports.debug = _exports.warn = _exports.info = _exports.assert = void 0;\n\n // These are the default production build versions:\n var noop = () => {};\n\n var assert = noop;\n _exports.assert = assert;\n var info = noop;\n _exports.info = info;\n var warn = noop;\n _exports.warn = warn;\n var debug = noop;\n _exports.debug = debug;\n var deprecate = noop;\n _exports.deprecate = deprecate;\n var debugSeal = noop;\n _exports.debugSeal = debugSeal;\n var debugFreeze = noop;\n _exports.debugFreeze = debugFreeze;\n var runInDebug = noop;\n _exports.runInDebug = runInDebug;\n var setDebugFunction = noop;\n _exports.setDebugFunction = setDebugFunction;\n var getDebugFunction = noop;\n _exports.getDebugFunction = getDebugFunction;\n\n var deprecateFunc = function () {\n return arguments[arguments.length - 1];\n };\n\n _exports.deprecateFunc = deprecateFunc;\n\n if (true\n /* DEBUG */\n ) {\n _exports.setDebugFunction = setDebugFunction = function (type, callback) {\n switch (type) {\n case 'assert':\n return _exports.assert = assert = callback;\n\n case 'info':\n return _exports.info = info = callback;\n\n case 'warn':\n return _exports.warn = warn = callback;\n\n case 'debug':\n return _exports.debug = debug = callback;\n\n case 'deprecate':\n return _exports.deprecate = deprecate = callback;\n\n case 'debugSeal':\n return _exports.debugSeal = debugSeal = callback;\n\n case 'debugFreeze':\n return _exports.debugFreeze = debugFreeze = callback;\n\n case 'runInDebug':\n return _exports.runInDebug = runInDebug = callback;\n\n case 'deprecateFunc':\n return _exports.deprecateFunc = deprecateFunc = callback;\n }\n };\n\n _exports.getDebugFunction = getDebugFunction = function (type) {\n switch (type) {\n case 'assert':\n return assert;\n\n case 'info':\n return info;\n\n case 'warn':\n return warn;\n\n case 'debug':\n return debug;\n\n case 'deprecate':\n return deprecate;\n\n case 'debugSeal':\n return debugSeal;\n\n case 'debugFreeze':\n return debugFreeze;\n\n case 'runInDebug':\n return runInDebug;\n\n case 'deprecateFunc':\n return deprecateFunc;\n }\n };\n }\n /**\n @module @ember/debug\n */\n\n\n if (true\n /* DEBUG */\n ) {\n /**\n Verify that a certain expectation is met, or throw a exception otherwise.\n This is useful for communicating assumptions in the code to other human\n readers as well as catching bugs that accidentally violates these\n expectations.\n Assertions are removed from production builds, so they can be freely added\n for documentation and debugging purposes without worries of incuring any\n performance penalty. However, because of that, they should not be used for\n checks that could reasonably fail during normal usage. Furthermore, care\n should be taken to avoid accidentally relying on side-effects produced from\n evaluating the condition itself, since the code will not run in production.\n ```javascript\n import { assert } from '@ember/debug';\n // Test for truthiness\n assert('Must pass a string', typeof str === 'string');\n // Fail unconditionally\n assert('This code path should never be run');\n ```\n @method assert\n @static\n @for @ember/debug\n @param {String} description Describes the expectation. This will become the\n text of the Error thrown if the assertion fails.\n @param {any} condition Must be truthy for the assertion to pass. If\n falsy, an exception will be thrown.\n @public\n @since 1.0.0\n */\n setDebugFunction('assert', function assert(desc, test) {\n if (!test) {\n throw new _error.default(`Assertion Failed: ${desc}`);\n }\n });\n /**\n Display a debug notice.\n Calls to this function are not invoked in production builds.\n ```javascript\n import { debug } from '@ember/debug';\n debug('I\\'m a debug notice!');\n ```\n @method debug\n @for @ember/debug\n @static\n @param {String} message A debug message to display.\n @public\n */\n\n setDebugFunction('debug', function debug(message) {\n /* eslint-disable no-console */\n if (console.debug) {\n console.debug(`DEBUG: ${message}`);\n } else {\n console.log(`DEBUG: ${message}`);\n }\n /* eslint-ensable no-console */\n\n });\n /**\n Display an info notice.\n Calls to this function are removed from production builds, so they can be\n freely added for documentation and debugging purposes without worries of\n incuring any performance penalty.\n @method info\n @private\n */\n\n setDebugFunction('info', function info() {\n console.info(...arguments);\n /* eslint-disable-line no-console */\n });\n /**\n @module @ember/debug\n @public\n */\n\n /**\n Alias an old, deprecated method with its new counterpart.\n Display a deprecation warning with the provided message and a stack trace\n (Chrome and Firefox only) when the assigned method is called.\n Calls to this function are removed from production builds, so they can be\n freely added for documentation and debugging purposes without worries of\n incuring any performance penalty.\n ```javascript\n import { deprecateFunc } from '@ember/debug';\n Ember.oldMethod = deprecateFunc('Please use the new, updated method', options, Ember.newMethod);\n ```\n @method deprecateFunc\n @static\n @for @ember/debug\n @param {String} message A description of the deprecation.\n @param {Object} [options] The options object for `deprecate`.\n @param {Function} func The new function called to replace its deprecated counterpart.\n @return {Function} A new function that wraps the original function with a deprecation warning\n @private\n */\n\n setDebugFunction('deprecateFunc', function deprecateFunc(...args) {\n if (args.length === 3) {\n var [message, options, func] = args;\n return function (...args) {\n deprecate(message, false, options);\n return func.apply(this, args);\n };\n } else {\n var [_message, _func] = args;\n return function () {\n deprecate(_message);\n return _func.apply(this, arguments);\n };\n }\n });\n /**\n @module @ember/debug\n @public\n */\n\n /**\n Run a function meant for debugging.\n Calls to this function are removed from production builds, so they can be\n freely added for documentation and debugging purposes without worries of\n incuring any performance penalty.\n ```javascript\n import Component from '@ember/component';\n import { runInDebug } from '@ember/debug';\n runInDebug(() => {\n Component.reopen({\n didInsertElement() {\n console.log(\"I'm happy\");\n }\n });\n });\n ```\n @method runInDebug\n @for @ember/debug\n @static\n @param {Function} func The function to be executed.\n @since 1.5.0\n @public\n */\n\n setDebugFunction('runInDebug', function runInDebug(func) {\n func();\n });\n setDebugFunction('debugSeal', function debugSeal(obj) {\n Object.seal(obj);\n });\n setDebugFunction('debugFreeze', function debugFreeze(obj) {\n // re-freezing an already frozen object introduces a significant\n // performance penalty on Chrome (tested through 59).\n //\n // See: https://bugs.chromium.org/p/v8/issues/detail?id=6450\n if (!Object.isFrozen(obj)) {\n Object.freeze(obj);\n }\n });\n setDebugFunction('deprecate', _deprecate2.default);\n setDebugFunction('warn', _warn2.default);\n }\n\n var _warnIfUsingStrippedFeatureFlags;\n\n _exports._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags;\n\n if (true\n /* DEBUG */\n && !(0, _testing.isTesting)()) {\n if (typeof window !== 'undefined' && (_browserEnvironment.isFirefox || _browserEnvironment.isChrome) && window.addEventListener) {\n window.addEventListener('load', () => {\n if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) {\n var downloadURL;\n\n if (_browserEnvironment.isChrome) {\n downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi';\n } else if (_browserEnvironment.isFirefox) {\n downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/';\n }\n\n debug(`For more advanced debugging, install the Ember Inspector from ${downloadURL}`);\n }\n }, false);\n }\n }\n});","define(\"@ember/debug/lib/capture-render-tree\", [\"exports\", \"@glimmer/util\"], function (_exports, _util) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = captureRenderTree;\n\n /**\n @module @ember/debug\n */\n\n /**\n Ember Inspector calls this function to capture the current render tree.\n \n In production mode, this requires turning on `ENV._DEBUG_RENDER_TREE`\n before loading Ember.\n \n @private\n @static\n @method captureRenderTree\n @for @ember/debug\n @param app {ApplicationInstance} An `ApplicationInstance`.\n @since 3.14.0\n */\n function captureRenderTree(app) {\n var renderer = (0, _util.expect)(app.lookup('renderer:-dom'), `BUG: owner is missing renderer`);\n return renderer.debugRenderTree.capture();\n }\n});","define(\"@ember/debug/lib/deprecate\", [\"exports\", \"@ember/-internals/environment\", \"@ember/debug/index\", \"@ember/debug/lib/handlers\"], function (_exports, _environment, _index, _handlers) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.missingOptionDeprecation = _exports.missingOptionsIdDeprecation = _exports.missingOptionsDeprecation = _exports.registerHandler = _exports.default = void 0;\n\n /**\n @module @ember/debug\n @public\n */\n\n /**\n Allows for runtime registration of handler functions that override the default deprecation behavior.\n Deprecations are invoked by calls to [@ember/debug/deprecate](/ember/release/classes/@ember%2Fdebug/methods/deprecate?anchor=deprecate).\n The following example demonstrates its usage by registering a handler that throws an error if the\n message contains the word \"should\", otherwise defers to the default handler.\n \n ```javascript\n import { registerDeprecationHandler } from '@ember/debug';\n \n registerDeprecationHandler((message, options, next) => {\n if (message.indexOf('should') !== -1) {\n throw new Error(`Deprecation message with should: ${message}`);\n } else {\n // defer to whatever handler was registered before this one\n next(message, options);\n }\n });\n ```\n \n The handler function takes the following arguments:\n \n
    \n
  • message - The message received from the deprecation call.
  • \n
  • options - An object passed in with the deprecation call containing additional information including:
  • \n
      \n
    • id - An id of the deprecation in the form of package-name.specific-deprecation.
    • \n
    • until - The Ember version number the feature and deprecation will be removed in.
    • \n
    \n
  • next - A function that calls into the previously registered handler.
  • \n
\n \n @public\n @static\n @method registerDeprecationHandler\n @for @ember/debug\n @param handler {Function} A function to handle deprecation calls.\n @since 2.1.0\n */\n var registerHandler = () => {};\n\n _exports.registerHandler = registerHandler;\n var missingOptionsDeprecation;\n _exports.missingOptionsDeprecation = missingOptionsDeprecation;\n var missingOptionsIdDeprecation;\n _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation;\n\n var missingOptionDeprecation = () => '';\n\n _exports.missingOptionDeprecation = missingOptionDeprecation;\n\n var deprecate = () => {};\n\n if (true\n /* DEBUG */\n ) {\n _exports.registerHandler = registerHandler = function registerHandler(handler) {\n (0, _handlers.registerHandler)('deprecate', handler);\n };\n\n var formatMessage = function formatMessage(_message, options) {\n var message = _message;\n\n if (options && options.id) {\n message = message + ` [deprecation id: ${options.id}]`;\n }\n\n if (options && options.url) {\n message += ` See ${options.url} for more details.`;\n }\n\n return message;\n };\n\n registerHandler(function logDeprecationToConsole(message, options) {\n var updatedMessage = formatMessage(message, options);\n console.warn(`DEPRECATION: ${updatedMessage}`); // eslint-disable-line no-console\n });\n var captureErrorForStack;\n\n if (new Error().stack) {\n captureErrorForStack = () => new Error();\n } else {\n captureErrorForStack = () => {\n try {\n __fail__.fail();\n } catch (e) {\n return e;\n }\n };\n }\n\n registerHandler(function logDeprecationStackTrace(message, options, next) {\n if (_environment.ENV.LOG_STACKTRACE_ON_DEPRECATION) {\n var stackStr = '';\n var error = captureErrorForStack();\n var stack;\n\n if (error.stack) {\n if (error['arguments']) {\n // Chrome\n stack = error.stack.replace(/^\\s+at\\s+/gm, '').replace(/^([^(]+?)([\\n$])/gm, '{anonymous}($1)$2').replace(/^Object.\\s*\\(([^)]+)\\)/gm, '{anonymous}($1)').split('\\n');\n stack.shift();\n } else {\n // Firefox\n stack = error.stack.replace(/(?:\\n@:0)?\\s+$/m, '').replace(/^\\(/gm, '{anonymous}(').split('\\n');\n }\n\n stackStr = `\\n ${stack.slice(2).join('\\n ')}`;\n }\n\n var updatedMessage = formatMessage(message, options);\n console.warn(`DEPRECATION: ${updatedMessage}${stackStr}`); // eslint-disable-line no-console\n } else {\n next(message, options);\n }\n });\n registerHandler(function raiseOnDeprecation(message, options, next) {\n if (_environment.ENV.RAISE_ON_DEPRECATION) {\n var updatedMessage = formatMessage(message);\n throw new Error(updatedMessage);\n } else {\n next(message, options);\n }\n });\n _exports.missingOptionsDeprecation = missingOptionsDeprecation = 'When calling `deprecate` you ' + 'must provide an `options` hash as the third parameter. ' + '`options` should include `id` and `until` properties.';\n _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation = 'When calling `deprecate` you must provide `id` in options.';\n\n _exports.missingOptionDeprecation = missingOptionDeprecation = (id, missingOption) => {\n return `When calling \\`deprecate\\` you must provide \\`${missingOption}\\` in options. Missing options.${missingOption} in \"${id}\" deprecation`;\n };\n /**\n @module @ember/debug\n @public\n */\n\n /**\n Display a deprecation warning with the provided message and a stack trace\n (Chrome and Firefox only).\n * In a production build, this method is defined as an empty function (NOP).\n Uses of this method in Ember itself are stripped from the ember.prod.js build.\n @method deprecate\n @for @ember/debug\n @param {String} message A description of the deprecation.\n @param {Boolean} test A boolean. If falsy, the deprecation will be displayed.\n @param {Object} options\n @param {String} options.id A unique id for this deprecation. The id can be\n used by Ember debugging tools to change the behavior (raise, log or silence)\n for that specific deprecation. The id should be namespaced by dots, e.g.\n \"view.helper.select\".\n @param {string} options.until The version of Ember when this deprecation\n warning will be removed.\n @param {String} options.for A namespace for the deprecation, usually the package name\n @param {Object} options.since Describes when the deprecation became available and enabled.\n @param {String} [options.url] An optional url to the transition guide on the\n emberjs.com website.\n @static\n @public\n @since 1.0.0\n */\n\n\n deprecate = function deprecate(message, test, options) {\n (0, _index.assert)(missingOptionsDeprecation, Boolean(options && (options.id || options.until)));\n (0, _index.assert)(missingOptionsIdDeprecation, Boolean(options.id));\n (0, _index.assert)(missingOptionDeprecation(options.id, 'until'), Boolean(options.until));\n (0, _index.assert)(missingOptionDeprecation(options.id, 'for'), Boolean(options.for));\n (0, _index.assert)(missingOptionDeprecation(options.id, 'since'), Boolean(options.since));\n (0, _handlers.invoke)('deprecate', message, test, options);\n };\n }\n\n var _default = deprecate;\n _exports.default = _default;\n});","define(\"@ember/debug/lib/handlers\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.invoke = _exports.registerHandler = _exports.HANDLERS = void 0;\n var HANDLERS = {};\n _exports.HANDLERS = HANDLERS;\n\n var registerHandler = () => {};\n\n _exports.registerHandler = registerHandler;\n\n var invoke = () => {};\n\n _exports.invoke = invoke;\n\n if (true\n /* DEBUG */\n ) {\n _exports.registerHandler = registerHandler = function registerHandler(type, callback) {\n var nextHandler = HANDLERS[type] || (() => {});\n\n HANDLERS[type] = (message, options) => {\n callback(message, options, nextHandler);\n };\n };\n\n _exports.invoke = invoke = function invoke(type, message, test, options) {\n if (test) {\n return;\n }\n\n var handlerForType = HANDLERS[type];\n\n if (handlerForType) {\n handlerForType(message, options);\n }\n };\n }\n});","define(\"@ember/debug/lib/testing\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.isTesting = isTesting;\n _exports.setTesting = setTesting;\n var testing = false;\n\n function isTesting() {\n return testing;\n }\n\n function setTesting(value) {\n testing = Boolean(value);\n }\n});","define(\"@ember/debug/lib/warn\", [\"exports\", \"@ember/debug/index\", \"@ember/debug/lib/handlers\"], function (_exports, _index, _handlers) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.missingOptionsDeprecation = _exports.missingOptionsIdDeprecation = _exports.registerHandler = _exports.default = void 0;\n\n var registerHandler = () => {};\n\n _exports.registerHandler = registerHandler;\n\n var warn = () => {};\n\n var missingOptionsDeprecation;\n _exports.missingOptionsDeprecation = missingOptionsDeprecation;\n var missingOptionsIdDeprecation;\n /**\n @module @ember/debug\n */\n\n _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation;\n\n if (true\n /* DEBUG */\n ) {\n /**\n Allows for runtime registration of handler functions that override the default warning behavior.\n Warnings are invoked by calls made to [@ember/debug/warn](/ember/release/classes/@ember%2Fdebug/methods/warn?anchor=warn).\n The following example demonstrates its usage by registering a handler that does nothing overriding Ember's\n default warning behavior.\n ```javascript\n import { registerWarnHandler } from '@ember/debug';\n // next is not called, so no warnings get the default behavior\n registerWarnHandler(() => {});\n ```\n The handler function takes the following arguments:\n
    \n
  • message - The message received from the warn call.
  • \n
  • options - An object passed in with the warn call containing additional information including:
  • \n
      \n
    • id - An id of the warning in the form of package-name.specific-warning.
    • \n
    \n
  • next - A function that calls into the previously registered handler.
  • \n
\n @public\n @static\n @method registerWarnHandler\n @for @ember/debug\n @param handler {Function} A function to handle warnings.\n @since 2.1.0\n */\n _exports.registerHandler = registerHandler = function registerHandler(handler) {\n (0, _handlers.registerHandler)('warn', handler);\n };\n\n registerHandler(function logWarning(message) {\n /* eslint-disable no-console */\n console.warn(`WARNING: ${message}`);\n /* eslint-enable no-console */\n });\n _exports.missingOptionsDeprecation = missingOptionsDeprecation = 'When calling `warn` you ' + 'must provide an `options` hash as the third parameter. ' + '`options` should include an `id` property.';\n _exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation = 'When calling `warn` you must provide `id` in options.';\n /**\n Display a warning with the provided message.\n * In a production build, this method is defined as an empty function (NOP).\n Uses of this method in Ember itself are stripped from the ember.prod.js build.\n ```javascript\n import { warn } from '@ember/debug';\n import tomsterCount from './tomster-counter'; // a module in my project\n // Log a warning if we have more than 3 tomsters\n warn('Too many tomsters!', tomsterCount <= 3, {\n id: 'ember-debug.too-many-tomsters'\n });\n ```\n @method warn\n @for @ember/debug\n @static\n @param {String} message A warning to display.\n @param {Boolean} test An optional boolean. If falsy, the warning\n will be displayed.\n @param {Object} options An object that can be used to pass a unique\n `id` for this warning. The `id` can be used by Ember debugging tools\n to change the behavior (raise, log, or silence) for that specific warning.\n The `id` should be namespaced by dots, e.g. \"ember-debug.feature-flag-with-features-stripped\"\n @public\n @since 1.0.0\n */\n\n warn = function warn(message, test, options) {\n if (arguments.length === 2 && typeof test === 'object') {\n options = test;\n test = false;\n }\n\n (0, _index.assert)(missingOptionsDeprecation, Boolean(options));\n (0, _index.assert)(missingOptionsIdDeprecation, Boolean(options && options.id));\n (0, _handlers.invoke)('warn', message, test, options);\n };\n }\n\n var _default = warn;\n _exports.default = _default;\n});","define(\"ember-testing/index\", [\"exports\", \"ember-testing/lib/test\", \"ember-testing/lib/adapters/adapter\", \"ember-testing/lib/setup_for_testing\", \"ember-testing/lib/adapters/qunit\", \"ember-testing/lib/ext/application\", \"ember-testing/lib/ext/rsvp\", \"ember-testing/lib/helpers\", \"ember-testing/lib/initializers\"], function (_exports, _test, _adapter, _setup_for_testing, _qunit, _application, _rsvp, _helpers, _initializers) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n Object.defineProperty(_exports, \"Test\", {\n enumerable: true,\n get: function () {\n return _test.default;\n }\n });\n Object.defineProperty(_exports, \"Adapter\", {\n enumerable: true,\n get: function () {\n return _adapter.default;\n }\n });\n Object.defineProperty(_exports, \"setupForTesting\", {\n enumerable: true,\n get: function () {\n return _setup_for_testing.default;\n }\n });\n Object.defineProperty(_exports, \"QUnitAdapter\", {\n enumerable: true,\n get: function () {\n return _qunit.default;\n }\n });\n});","define(\"ember-testing/lib/adapters/adapter\", [\"exports\", \"@ember/-internals/runtime\"], function (_exports, _runtime) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n function K() {\n return this;\n }\n /**\n @module @ember/test\n */\n\n /**\n The primary purpose of this class is to create hooks that can be implemented\n by an adapter for various test frameworks.\n \n @class TestAdapter\n @public\n */\n\n\n var _default = _runtime.Object.extend({\n /**\n This callback will be called whenever an async operation is about to start.\n Override this to call your framework's methods that handle async\n operations.\n @public\n @method asyncStart\n */\n asyncStart: K,\n\n /**\n This callback will be called whenever an async operation has completed.\n @public\n @method asyncEnd\n */\n asyncEnd: K,\n\n /**\n Override this method with your testing framework's false assertion.\n This function is called whenever an exception occurs causing the testing\n promise to fail.\n QUnit example:\n ```javascript\n exception: function(error) {\n ok(false, error);\n };\n ```\n @public\n @method exception\n @param {String} error The exception to be raised.\n */\n exception(error) {\n throw error;\n }\n\n });\n\n _exports.default = _default;\n});","define(\"ember-testing/lib/adapters/qunit\", [\"exports\", \"@ember/-internals/utils\", \"ember-testing/lib/adapters/adapter\"], function (_exports, _utils, _adapter) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n /* globals QUnit */\n\n /**\n @module ember\n */\n\n /**\n This class implements the methods defined by TestAdapter for the\n QUnit testing framework.\n \n @class QUnitAdapter\n @namespace Ember.Test\n @extends TestAdapter\n @public\n */\n var _default = _adapter.default.extend({\n init() {\n this.doneCallbacks = [];\n },\n\n asyncStart() {\n if (typeof QUnit.stop === 'function') {\n // very old QUnit version\n // eslint-disable-next-line qunit/no-qunit-stop\n QUnit.stop();\n } else {\n this.doneCallbacks.push(QUnit.config.current ? QUnit.config.current.assert.async() : null);\n }\n },\n\n asyncEnd() {\n // checking for QUnit.stop here (even though we _need_ QUnit.start) because\n // QUnit.start() still exists in QUnit 2.x (it just throws an error when calling\n // inside a test context)\n if (typeof QUnit.stop === 'function') {\n QUnit.start();\n } else {\n var done = this.doneCallbacks.pop(); // This can be null if asyncStart() was called outside of a test\n\n if (done) {\n done();\n }\n }\n },\n\n exception(error) {\n QUnit.config.current.assert.ok(false, (0, _utils.inspect)(error));\n }\n\n });\n\n _exports.default = _default;\n});","define(\"ember-testing/lib/ext/application\", [\"@ember/application\", \"ember-testing/lib/setup_for_testing\", \"ember-testing/lib/test/helpers\", \"ember-testing/lib/test/promise\", \"ember-testing/lib/test/run\", \"ember-testing/lib/test/on_inject_helpers\", \"ember-testing/lib/test/adapter\"], function (_application, _setup_for_testing, _helpers, _promise, _run, _on_inject_helpers, _adapter) {\n \"use strict\";\n\n _application.default.reopen({\n /**\n This property contains the testing helpers for the current application. These\n are created once you call `injectTestHelpers` on your `Application`\n instance. The included helpers are also available on the `window` object by\n default, but can be used from this object on the individual application also.\n @property testHelpers\n @type {Object}\n @default {}\n @public\n */\n testHelpers: {},\n\n /**\n This property will contain the original methods that were registered\n on the `helperContainer` before `injectTestHelpers` is called.\n When `removeTestHelpers` is called, these methods are restored to the\n `helperContainer`.\n @property originalMethods\n @type {Object}\n @default {}\n @private\n @since 1.3.0\n */\n originalMethods: {},\n\n /**\n This property indicates whether or not this application is currently in\n testing mode. This is set when `setupForTesting` is called on the current\n application.\n @property testing\n @type {Boolean}\n @default false\n @since 1.3.0\n @public\n */\n testing: false,\n\n /**\n This hook defers the readiness of the application, so that you can start\n the app when your tests are ready to run. It also sets the router's\n location to 'none', so that the window's location will not be modified\n (preventing both accidental leaking of state between tests and interference\n with your testing framework). `setupForTesting` should only be called after\n setting a custom `router` class (for example `App.Router = Router.extend(`).\n Example:\n ```\n App.setupForTesting();\n ```\n @method setupForTesting\n @public\n */\n setupForTesting() {\n (0, _setup_for_testing.default)();\n this.testing = true;\n this.resolveRegistration('router:main').reopen({\n location: 'none'\n });\n },\n\n /**\n This will be used as the container to inject the test helpers into. By\n default the helpers are injected into `window`.\n @property helperContainer\n @type {Object} The object to be used for test helpers.\n @default window\n @since 1.2.0\n @private\n */\n helperContainer: null,\n\n /**\n This injects the test helpers into the `helperContainer` object. If an object is provided\n it will be used as the helperContainer. If `helperContainer` is not set it will default\n to `window`. If a function of the same name has already been defined it will be cached\n (so that it can be reset if the helper is removed with `unregisterHelper` or\n `removeTestHelpers`).\n Any callbacks registered with `onInjectHelpers` will be called once the\n helpers have been injected.\n Example:\n ```\n App.injectTestHelpers();\n ```\n @method injectTestHelpers\n @public\n */\n injectTestHelpers(helperContainer) {\n if (helperContainer) {\n this.helperContainer = helperContainer;\n } else {\n this.helperContainer = window;\n }\n\n this.reopen({\n willDestroy() {\n this._super(...arguments);\n\n this.removeTestHelpers();\n }\n\n });\n this.testHelpers = {};\n\n for (var name in _helpers.helpers) {\n this.originalMethods[name] = this.helperContainer[name];\n this.testHelpers[name] = this.helperContainer[name] = helper(this, name);\n protoWrap(_promise.default.prototype, name, helper(this, name), _helpers.helpers[name].meta.wait);\n }\n\n (0, _on_inject_helpers.invokeInjectHelpersCallbacks)(this);\n },\n\n /**\n This removes all helpers that have been registered, and resets and functions\n that were overridden by the helpers.\n Example:\n ```javascript\n App.removeTestHelpers();\n ```\n @public\n @method removeTestHelpers\n */\n removeTestHelpers() {\n if (!this.helperContainer) {\n return;\n }\n\n for (var name in _helpers.helpers) {\n this.helperContainer[name] = this.originalMethods[name];\n delete _promise.default.prototype[name];\n delete this.testHelpers[name];\n delete this.originalMethods[name];\n }\n }\n\n }); // This method is no longer needed\n // But still here for backwards compatibility\n // of helper chaining\n\n\n function protoWrap(proto, name, callback, isAsync) {\n proto[name] = function (...args) {\n if (isAsync) {\n return callback.apply(this, args);\n } else {\n return this.then(function () {\n return callback.apply(this, args);\n });\n }\n };\n }\n\n function helper(app, name) {\n var fn = _helpers.helpers[name].method;\n var meta = _helpers.helpers[name].meta;\n\n if (!meta.wait) {\n return (...args) => fn.apply(app, [app, ...args]);\n }\n\n return (...args) => {\n var lastPromise = (0, _run.default)(() => (0, _promise.resolve)((0, _promise.getLastPromise)())); // wait for last helper's promise to resolve and then\n // execute. To be safe, we need to tell the adapter we're going\n // asynchronous here, because fn may not be invoked before we\n // return.\n\n (0, _adapter.asyncStart)();\n return lastPromise.then(() => fn.apply(app, [app, ...args])).finally(_adapter.asyncEnd);\n };\n }\n});","define(\"ember-testing/lib/ext/rsvp\", [\"exports\", \"@ember/-internals/runtime\", \"@ember/runloop\", \"@ember/debug\", \"ember-testing/lib/test/adapter\"], function (_exports, _runtime, _runloop, _debug, _adapter) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n _runtime.RSVP.configure('async', function (callback, promise) {\n // if schedule will cause autorun, we need to inform adapter\n if ((0, _debug.isTesting)() && !_runloop._backburner.currentInstance) {\n (0, _adapter.asyncStart)();\n\n _runloop._backburner.schedule('actions', () => {\n (0, _adapter.asyncEnd)();\n callback(promise);\n });\n } else {\n _runloop._backburner.schedule('actions', () => callback(promise));\n }\n });\n\n var _default = _runtime.RSVP;\n _exports.default = _default;\n});","define(\"ember-testing/lib/helpers\", [\"ember-testing/lib/test/helpers\", \"ember-testing/lib/helpers/and_then\", \"ember-testing/lib/helpers/current_path\", \"ember-testing/lib/helpers/current_route_name\", \"ember-testing/lib/helpers/current_url\", \"ember-testing/lib/helpers/pause_test\", \"ember-testing/lib/helpers/visit\", \"ember-testing/lib/helpers/wait\"], function (_helpers, _and_then, _current_path, _current_route_name, _current_url, _pause_test, _visit, _wait) {\n \"use strict\";\n\n (0, _helpers.registerAsyncHelper)('visit', _visit.default);\n (0, _helpers.registerAsyncHelper)('wait', _wait.default);\n (0, _helpers.registerAsyncHelper)('andThen', _and_then.default);\n (0, _helpers.registerAsyncHelper)('pauseTest', _pause_test.pauseTest);\n (0, _helpers.registerHelper)('currentRouteName', _current_route_name.default);\n (0, _helpers.registerHelper)('currentPath', _current_path.default);\n (0, _helpers.registerHelper)('currentURL', _current_url.default);\n (0, _helpers.registerHelper)('resumeTest', _pause_test.resumeTest);\n});","define(\"ember-testing/lib/helpers/and_then\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = andThen;\n\n function andThen(app, callback) {\n return app.testHelpers.wait(callback(app));\n }\n});","define(\"ember-testing/lib/helpers/current_path\", [\"exports\", \"@ember/-internals/metal\"], function (_exports, _metal) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = currentPath;\n\n /**\n @module ember\n */\n\n /**\n Returns the current path.\n \n Example:\n \n ```javascript\n function validateURL() {\n equal(currentPath(), 'some.path.index', \"correct path was transitioned into.\");\n }\n \n click('#some-link-id').then(validateURL);\n ```\n \n @method currentPath\n @return {Object} The currently active path.\n @since 1.5.0\n @public\n */\n function currentPath(app) {\n var routingService = app.__container__.lookup('service:-routing');\n\n return (0, _metal.get)(routingService, 'currentPath');\n }\n});","define(\"ember-testing/lib/helpers/current_route_name\", [\"exports\", \"@ember/-internals/metal\"], function (_exports, _metal) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = currentRouteName;\n\n /**\n @module ember\n */\n\n /**\n Returns the currently active route name.\n \n Example:\n \n ```javascript\n function validateRouteName() {\n equal(currentRouteName(), 'some.path', \"correct route was transitioned into.\");\n }\n visit('/some/path').then(validateRouteName)\n ```\n \n @method currentRouteName\n @return {Object} The name of the currently active route.\n @since 1.5.0\n @public\n */\n function currentRouteName(app) {\n var routingService = app.__container__.lookup('service:-routing');\n\n return (0, _metal.get)(routingService, 'currentRouteName');\n }\n});","define(\"ember-testing/lib/helpers/current_url\", [\"exports\", \"@ember/-internals/metal\"], function (_exports, _metal) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = currentURL;\n\n /**\n @module ember\n */\n\n /**\n Returns the current URL.\n \n Example:\n \n ```javascript\n function validateURL() {\n equal(currentURL(), '/some/path', \"correct URL was transitioned into.\");\n }\n \n click('#some-link-id').then(validateURL);\n ```\n \n @method currentURL\n @return {Object} The currently active URL.\n @since 1.5.0\n @public\n */\n function currentURL(app) {\n var router = app.__container__.lookup('router:main');\n\n return (0, _metal.get)(router, 'location').getURL();\n }\n});","define(\"ember-testing/lib/helpers/pause_test\", [\"exports\", \"@ember/-internals/runtime\", \"@ember/debug\"], function (_exports, _runtime, _debug) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.resumeTest = resumeTest;\n _exports.pauseTest = pauseTest;\n\n /**\n @module ember\n */\n var resume;\n /**\n Resumes a test paused by `pauseTest`.\n \n @method resumeTest\n @return {void}\n @public\n */\n\n function resumeTest() {\n (true && !(resume) && (0, _debug.assert)('Testing has not been paused. There is nothing to resume.', resume));\n resume();\n resume = undefined;\n }\n /**\n Pauses the current test - this is useful for debugging while testing or for test-driving.\n It allows you to inspect the state of your application at any point.\n Example (The test will pause before clicking the button):\n \n ```javascript\n visit('/')\n return pauseTest();\n click('.btn');\n ```\n \n You may want to turn off the timeout before pausing.\n \n qunit (timeout available to use as of 2.4.0):\n \n ```\n visit('/');\n assert.timeout(0);\n return pauseTest();\n click('.btn');\n ```\n \n mocha (timeout happens automatically as of ember-mocha v0.14.0):\n \n ```\n visit('/');\n this.timeout(0);\n return pauseTest();\n click('.btn');\n ```\n \n \n @since 1.9.0\n @method pauseTest\n @return {Object} A promise that will never resolve\n @public\n */\n\n\n function pauseTest() {\n (0, _debug.info)('Testing paused. Use `resumeTest()` to continue.');\n return new _runtime.RSVP.Promise(resolve => {\n resume = resolve;\n }, 'TestAdapter paused promise');\n }\n});","define(\"ember-testing/lib/helpers/visit\", [\"exports\", \"@ember/runloop\"], function (_exports, _runloop) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = visit;\n\n /**\n Loads a route, sets up any controllers, and renders any templates associated\n with the route as though a real user had triggered the route change while\n using your app.\n \n Example:\n \n ```javascript\n visit('posts/index').then(function() {\n // assert something\n });\n ```\n \n @method visit\n @param {String} url the name of the route\n @return {RSVP.Promise}\n @public\n */\n function visit(app, url) {\n var router = app.__container__.lookup('router:main');\n\n var shouldHandleURL = false;\n app.boot().then(() => {\n router.location.setURL(url);\n\n if (shouldHandleURL) {\n (0, _runloop.run)(app.__deprecatedInstance__, 'handleURL', url);\n }\n });\n\n if (app._readinessDeferrals > 0) {\n router.initialURL = url;\n (0, _runloop.run)(app, 'advanceReadiness');\n delete router.initialURL;\n } else {\n shouldHandleURL = true;\n }\n\n return app.testHelpers.wait();\n }\n});","define(\"ember-testing/lib/helpers/wait\", [\"exports\", \"ember-testing/lib/test/waiters\", \"@ember/-internals/runtime\", \"@ember/runloop\", \"ember-testing/lib/test/pending_requests\"], function (_exports, _waiters, _runtime, _runloop, _pending_requests) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = wait;\n\n /**\n @module ember\n */\n\n /**\n Causes the run loop to process any pending events. This is used to ensure that\n any async operations from other helpers (or your assertions) have been processed.\n \n This is most often used as the return value for the helper functions (see 'click',\n 'fillIn','visit',etc). However, there is a method to register a test helper which\n utilizes this method without the need to actually call `wait()` in your helpers.\n \n The `wait` helper is built into `registerAsyncHelper` by default. You will not need\n to `return app.testHelpers.wait();` - the wait behavior is provided for you.\n \n Example:\n \n ```javascript\n import { registerAsyncHelper } from '@ember/test';\n \n registerAsyncHelper('loginUser', function(app, username, password) {\n visit('secured/path/here')\n .fillIn('#username', username)\n .fillIn('#password', password)\n .click('.submit');\n });\n ```\n \n @method wait\n @param {Object} value The value to be returned.\n @return {RSVP.Promise} Promise that resolves to the passed value.\n @public\n @since 1.0.0\n */\n function wait(app, value) {\n return new _runtime.RSVP.Promise(function (resolve) {\n var router = app.__container__.lookup('router:main'); // Every 10ms, poll for the async thing to have finished\n\n\n var watcher = setInterval(() => {\n // 1. If the router is loading, keep polling\n var routerIsLoading = router._routerMicrolib && Boolean(router._routerMicrolib.activeTransition);\n\n if (routerIsLoading) {\n return;\n } // 2. If there are pending Ajax requests, keep polling\n\n\n if ((0, _pending_requests.pendingRequests)()) {\n return;\n } // 3. If there are scheduled timers or we are inside of a run loop, keep polling\n\n\n if ((0, _runloop._hasScheduledTimers)() || (0, _runloop._getCurrentRunLoop)()) {\n return;\n }\n\n if ((0, _waiters.checkWaiters)()) {\n return;\n } // Stop polling\n\n\n clearInterval(watcher); // Synchronously resolve the promise\n\n (0, _runloop.run)(null, resolve, value);\n }, 10);\n });\n }\n});","define(\"ember-testing/lib/initializers\", [\"@ember/application\"], function (_application) {\n \"use strict\";\n\n var name = 'deferReadiness in `testing` mode';\n (0, _application.onLoad)('Ember.Application', function (Application) {\n if (!Application.initializers[name]) {\n Application.initializer({\n name: name,\n\n initialize(application) {\n if (application.testing) {\n application.deferReadiness();\n }\n }\n\n });\n }\n });\n});","define(\"ember-testing/lib/setup_for_testing\", [\"exports\", \"@ember/debug\", \"ember-testing/lib/test/adapter\", \"ember-testing/lib/adapters/adapter\", \"ember-testing/lib/adapters/qunit\"], function (_exports, _debug, _adapter, _adapter2, _qunit) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = setupForTesting;\n\n /* global self */\n\n /**\n Sets Ember up for testing. This is useful to perform\n basic setup steps in order to unit test.\n \n Use `App.setupForTesting` to perform integration tests (full\n application testing).\n \n @method setupForTesting\n @namespace Ember\n @since 1.5.0\n @private\n */\n function setupForTesting() {\n (0, _debug.setTesting)(true);\n var adapter = (0, _adapter.getAdapter)(); // if adapter is not manually set default to QUnit\n\n if (!adapter) {\n (0, _adapter.setAdapter)(typeof self.QUnit === 'undefined' ? _adapter2.default.create() : _qunit.default.create());\n }\n }\n});","define(\"ember-testing/lib/test\", [\"exports\", \"ember-testing/lib/test/helpers\", \"ember-testing/lib/test/on_inject_helpers\", \"ember-testing/lib/test/promise\", \"ember-testing/lib/test/waiters\", \"ember-testing/lib/test/adapter\"], function (_exports, _helpers, _on_inject_helpers, _promise, _waiters, _adapter) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = void 0;\n\n /**\n @module ember\n */\n\n /**\n This is a container for an assortment of testing related functionality:\n \n * Choose your default test adapter (for your framework of choice).\n * Register/Unregister additional test helpers.\n * Setup callbacks to be fired when the test helpers are injected into\n your application.\n \n @class Test\n @namespace Ember\n @public\n */\n var Test = {\n /**\n Hash containing all known test helpers.\n @property _helpers\n @private\n @since 1.7.0\n */\n _helpers: _helpers.helpers,\n registerHelper: _helpers.registerHelper,\n registerAsyncHelper: _helpers.registerAsyncHelper,\n unregisterHelper: _helpers.unregisterHelper,\n onInjectHelpers: _on_inject_helpers.onInjectHelpers,\n Promise: _promise.default,\n promise: _promise.promise,\n resolve: _promise.resolve,\n registerWaiter: _waiters.registerWaiter,\n unregisterWaiter: _waiters.unregisterWaiter,\n checkWaiters: _waiters.checkWaiters\n };\n /**\n Used to allow ember-testing to communicate with a specific testing\n framework.\n \n You can manually set it before calling `App.setupForTesting()`.\n \n Example:\n \n ```javascript\n Ember.Test.adapter = MyCustomAdapter.create()\n ```\n \n If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`.\n \n @public\n @for Ember.Test\n @property adapter\n @type {Class} The adapter to be used.\n @default Ember.Test.QUnitAdapter\n */\n\n Object.defineProperty(Test, 'adapter', {\n get: _adapter.getAdapter,\n set: _adapter.setAdapter\n });\n var _default = Test;\n _exports.default = _default;\n});","define(\"ember-testing/lib/test/adapter\", [\"exports\", \"@ember/-internals/error-handling\"], function (_exports, _errorHandling) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.getAdapter = getAdapter;\n _exports.setAdapter = setAdapter;\n _exports.asyncStart = asyncStart;\n _exports.asyncEnd = asyncEnd;\n var adapter;\n\n function getAdapter() {\n return adapter;\n }\n\n function setAdapter(value) {\n adapter = value;\n\n if (value && typeof value.exception === 'function') {\n (0, _errorHandling.setDispatchOverride)(adapterDispatch);\n } else {\n (0, _errorHandling.setDispatchOverride)(null);\n }\n }\n\n function asyncStart() {\n if (adapter) {\n adapter.asyncStart();\n }\n }\n\n function asyncEnd() {\n if (adapter) {\n adapter.asyncEnd();\n }\n }\n\n function adapterDispatch(error) {\n adapter.exception(error);\n console.error(error.stack); // eslint-disable-line no-console\n }\n});","define(\"ember-testing/lib/test/helpers\", [\"exports\", \"ember-testing/lib/test/promise\"], function (_exports, _promise) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.registerHelper = registerHelper;\n _exports.registerAsyncHelper = registerAsyncHelper;\n _exports.unregisterHelper = unregisterHelper;\n _exports.helpers = void 0;\n var helpers = {};\n /**\n @module @ember/test\n */\n\n /**\n `registerHelper` is used to register a test helper that will be injected\n when `App.injectTestHelpers` is called.\n \n The helper method will always be called with the current Application as\n the first parameter.\n \n For example:\n \n ```javascript\n import { registerHelper } from '@ember/test';\n import { run } from '@ember/runloop';\n \n registerHelper('boot', function(app) {\n run(app, app.advanceReadiness);\n });\n ```\n \n This helper can later be called without arguments because it will be\n called with `app` as the first parameter.\n \n ```javascript\n import Application from '@ember/application';\n \n App = Application.create();\n App.injectTestHelpers();\n boot();\n ```\n \n @public\n @for @ember/test\n @static\n @method registerHelper\n @param {String} name The name of the helper method to add.\n @param {Function} helperMethod\n @param options {Object}\n */\n\n _exports.helpers = helpers;\n\n function registerHelper(name, helperMethod) {\n helpers[name] = {\n method: helperMethod,\n meta: {\n wait: false\n }\n };\n }\n /**\n `registerAsyncHelper` is used to register an async test helper that will be injected\n when `App.injectTestHelpers` is called.\n \n The helper method will always be called with the current Application as\n the first parameter.\n \n For example:\n \n ```javascript\n import { registerAsyncHelper } from '@ember/test';\n import { run } from '@ember/runloop';\n \n registerAsyncHelper('boot', function(app) {\n run(app, app.advanceReadiness);\n });\n ```\n \n The advantage of an async helper is that it will not run\n until the last async helper has completed. All async helpers\n after it will wait for it complete before running.\n \n \n For example:\n \n ```javascript\n import { registerAsyncHelper } from '@ember/test';\n \n registerAsyncHelper('deletePost', function(app, postId) {\n click('.delete-' + postId);\n });\n \n // ... in your test\n visit('/post/2');\n deletePost(2);\n visit('/post/3');\n deletePost(3);\n ```\n \n @public\n @for @ember/test\n @method registerAsyncHelper\n @param {String} name The name of the helper method to add.\n @param {Function} helperMethod\n @since 1.2.0\n */\n\n\n function registerAsyncHelper(name, helperMethod) {\n helpers[name] = {\n method: helperMethod,\n meta: {\n wait: true\n }\n };\n }\n /**\n Remove a previously added helper method.\n \n Example:\n \n ```javascript\n import { unregisterHelper } from '@ember/test';\n \n unregisterHelper('wait');\n ```\n \n @public\n @method unregisterHelper\n @static\n @for @ember/test\n @param {String} name The helper to remove.\n */\n\n\n function unregisterHelper(name) {\n delete helpers[name];\n delete _promise.default.prototype[name];\n }\n});","define(\"ember-testing/lib/test/on_inject_helpers\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.onInjectHelpers = onInjectHelpers;\n _exports.invokeInjectHelpersCallbacks = invokeInjectHelpersCallbacks;\n _exports.callbacks = void 0;\n var callbacks = [];\n /**\n Used to register callbacks to be fired whenever `App.injectTestHelpers`\n is called.\n \n The callback will receive the current application as an argument.\n \n Example:\n \n ```javascript\n import $ from 'jquery';\n \n Ember.Test.onInjectHelpers(function() {\n $(document).ajaxSend(function() {\n Test.pendingRequests++;\n });\n \n $(document).ajaxComplete(function() {\n Test.pendingRequests--;\n });\n });\n ```\n \n @public\n @for Ember.Test\n @method onInjectHelpers\n @param {Function} callback The function to be called.\n */\n\n _exports.callbacks = callbacks;\n\n function onInjectHelpers(callback) {\n callbacks.push(callback);\n }\n\n function invokeInjectHelpersCallbacks(app) {\n for (var i = 0; i < callbacks.length; i++) {\n callbacks[i](app);\n }\n }\n});","define(\"ember-testing/lib/test/pending_requests\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.pendingRequests = pendingRequests;\n _exports.clearPendingRequests = clearPendingRequests;\n _exports.incrementPendingRequests = incrementPendingRequests;\n _exports.decrementPendingRequests = decrementPendingRequests;\n var requests = [];\n\n function pendingRequests() {\n return requests.length;\n }\n\n function clearPendingRequests() {\n requests.length = 0;\n }\n\n function incrementPendingRequests(_, xhr) {\n requests.push(xhr);\n }\n\n function decrementPendingRequests(_, xhr) {\n setTimeout(function () {\n for (var i = 0; i < requests.length; i++) {\n if (xhr === requests[i]) {\n requests.splice(i, 1);\n break;\n }\n }\n }, 0);\n }\n});","define(\"ember-testing/lib/test/promise\", [\"exports\", \"@ember/-internals/runtime\", \"ember-testing/lib/test/run\"], function (_exports, _runtime, _run) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.promise = promise;\n _exports.resolve = resolve;\n _exports.getLastPromise = getLastPromise;\n _exports.default = void 0;\n var lastPromise;\n\n class TestPromise extends _runtime.RSVP.Promise {\n constructor() {\n super(...arguments);\n lastPromise = this;\n }\n\n then(_onFulfillment, ...args) {\n var onFulfillment = typeof _onFulfillment === 'function' ? result => isolate(_onFulfillment, result) : undefined;\n return super.then(onFulfillment, ...args);\n }\n\n }\n /**\n This returns a thenable tailored for testing. It catches failed\n `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception`\n callback in the last chained then.\n \n This method should be returned by async helpers such as `wait`.\n \n @public\n @for Ember.Test\n @method promise\n @param {Function} resolver The function used to resolve the promise.\n @param {String} label An optional string for identifying the promise.\n */\n\n\n _exports.default = TestPromise;\n\n function promise(resolver, label) {\n var fullLabel = `Ember.Test.promise: ${label || ''}`;\n return new TestPromise(resolver, fullLabel);\n }\n /**\n Replacement for `Ember.RSVP.resolve`\n The only difference is this uses\n an instance of `Ember.Test.Promise`\n \n @public\n @for Ember.Test\n @method resolve\n @param {Mixed} The value to resolve\n @since 1.2.0\n */\n\n\n function resolve(result, label) {\n return TestPromise.resolve(result, label);\n }\n\n function getLastPromise() {\n return lastPromise;\n } // This method isolates nested async methods\n // so that they don't conflict with other last promises.\n //\n // 1. Set `Ember.Test.lastPromise` to null\n // 2. Invoke method\n // 3. Return the last promise created during method\n\n\n function isolate(onFulfillment, result) {\n // Reset lastPromise for nested helpers\n lastPromise = null;\n var value = onFulfillment(result);\n var promise = lastPromise;\n lastPromise = null; // If the method returned a promise\n // return that promise. If not,\n // return the last async helper's promise\n\n if (value && value instanceof TestPromise || !promise) {\n return value;\n } else {\n return (0, _run.default)(() => resolve(promise).then(() => value));\n }\n }\n});","define(\"ember-testing/lib/test/run\", [\"exports\", \"@ember/runloop\"], function (_exports, _runloop) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.default = run;\n\n function run(fn) {\n if (!(0, _runloop._getCurrentRunLoop)()) {\n return (0, _runloop.run)(fn);\n } else {\n return fn();\n }\n }\n});","define(\"ember-testing/lib/test/waiters\", [\"exports\"], function (_exports) {\n \"use strict\";\n\n Object.defineProperty(_exports, \"__esModule\", {\n value: true\n });\n _exports.registerWaiter = registerWaiter;\n _exports.unregisterWaiter = unregisterWaiter;\n _exports.checkWaiters = checkWaiters;\n\n /**\n @module @ember/test\n */\n var contexts = [];\n var callbacks = [];\n /**\n This allows ember-testing to play nicely with other asynchronous\n events, such as an application that is waiting for a CSS3\n transition or an IndexDB transaction. The waiter runs periodically\n after each async helper (i.e. `click`, `andThen`, `visit`, etc) has executed,\n until the returning result is truthy. After the waiters finish, the next async helper\n is executed and the process repeats.\n \n For example:\n \n ```javascript\n import { registerWaiter } from '@ember/test';\n \n registerWaiter(function() {\n return myPendingTransactions() === 0;\n });\n ```\n The `context` argument allows you to optionally specify the `this`\n with which your callback will be invoked.\n \n For example:\n \n ```javascript\n import { registerWaiter } from '@ember/test';\n \n registerWaiter(MyDB, MyDB.hasPendingTransactions);\n ```\n \n @public\n @for @ember/test\n @static\n @method registerWaiter\n @param {Object} context (optional)\n @param {Function} callback\n @since 1.2.0\n */\n\n function registerWaiter(context, callback) {\n if (arguments.length === 1) {\n callback = context;\n context = null;\n }\n\n if (indexOf(context, callback) > -1) {\n return;\n }\n\n contexts.push(context);\n callbacks.push(callback);\n }\n /**\n `unregisterWaiter` is used to unregister a callback that was\n registered with `registerWaiter`.\n \n @public\n @for @ember/test\n @static\n @method unregisterWaiter\n @param {Object} context (optional)\n @param {Function} callback\n @since 1.2.0\n */\n\n\n function unregisterWaiter(context, callback) {\n if (!callbacks.length) {\n return;\n }\n\n if (arguments.length === 1) {\n callback = context;\n context = null;\n }\n\n var i = indexOf(context, callback);\n\n if (i === -1) {\n return;\n }\n\n contexts.splice(i, 1);\n callbacks.splice(i, 1);\n }\n /**\n Iterates through each registered test waiter, and invokes\n its callback. If any waiter returns false, this method will return\n true indicating that the waiters have not settled yet.\n \n This is generally used internally from the acceptance/integration test\n infrastructure.\n \n @public\n @for @ember/test\n @static\n @method checkWaiters\n */\n\n\n function checkWaiters() {\n if (!callbacks.length) {\n return false;\n }\n\n for (var i = 0; i < callbacks.length; i++) {\n var context = contexts[i];\n var callback = callbacks[i];\n\n if (!callback.call(context)) {\n return true;\n }\n }\n\n return false;\n }\n\n function indexOf(context, callback) {\n for (var i = 0; i < callbacks.length; i++) {\n if (callbacks[i] === callback && contexts[i] === context) {\n return i;\n }\n }\n\n return -1;\n }\n});"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;","file":"ember-testing.js"} \ No newline at end of file diff --git a/ember-vendored-pr-19806/ember.debug.js b/ember-vendored-pr-19806/ember.debug.js new file mode 100644 index 0000000..e168e4a --- /dev/null +++ b/ember-vendored-pr-19806/ember.debug.js @@ -0,0 +1,61482 @@ +(function() { +/*! + * @overview Ember - JavaScript Application Framework + * @copyright Copyright 2011-2021 Tilde Inc. and contributors + * Portions Copyright 2006-2011 Strobe Inc. + * Portions Copyright 2008-2011 Apple Inc. All rights reserved. + * @license Licensed under MIT license + * See https://raw.github.com/emberjs/ember.js/master/LICENSE + * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74 + */ +/* eslint-disable no-var */ + +/* globals global globalThis self */ + +/* eslint-disable-next-line no-unused-vars */ +var define, require; + +(function () { + var globalObj = typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : null; + + if (globalObj === null) { + throw new Error('unable to locate global object'); + } + + if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') { + define = globalObj.define; + require = globalObj.require; + return; + } + + var registry = Object.create(null); + var seen = Object.create(null); + + function missingModule(name, referrerName) { + if (referrerName) { + throw new Error('Could not find module ' + name + ' required by: ' + referrerName); + } else { + throw new Error('Could not find module ' + name); + } + } + + function internalRequire(_name, referrerName) { + var name = _name; + var mod = registry[name]; + + if (!mod) { + name = name + '/index'; + mod = registry[name]; + } + + var exports = seen[name]; + + if (exports !== undefined) { + return exports; + } + + exports = seen[name] = {}; + + if (!mod) { + missingModule(_name, referrerName); + } + + var deps = mod.deps; + var callback = mod.callback; + var reified = new Array(deps.length); + + for (var i = 0; i < deps.length; i++) { + if (deps[i] === 'exports') { + reified[i] = exports; + } else if (deps[i] === 'require') { + reified[i] = require; + } else { + reified[i] = require(deps[i], name); + } + } + + callback.apply(this, reified); + return exports; + } + + require = function (name) { + return internalRequire(name, null); + }; // eslint-disable-next-line no-unused-vars + + + define = function (name, deps, callback) { + registry[name] = { + deps: deps, + callback: callback + }; + }; // setup `require` module + + + require['default'] = require; + + require.has = function registryHas(moduleName) { + return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']); + }; + + require._eak_seen = require.entries = registry; +})(); +define("@ember/-internals/bootstrap/index", ["require"], function (_require) { + "use strict"; + + (function bootstrap() { + // Bootstrap Node module + // eslint-disable-next-line no-undef + if (typeof module === 'object' && typeof module.require === 'function') { + // tslint:disable-next-line: no-require-imports + module.exports = (0, _require.default)("ember").default; + } + })(); +}); +define("@ember/-internals/browser-environment/index", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.hasDOM = _exports.isIE = _exports.isFirefox = _exports.isChrome = _exports.userAgent = _exports.history = _exports.location = _exports.window = void 0; + // check if window exists and actually is the global + var hasDom = typeof self === 'object' && self !== null && self.Object === Object && typeof Window !== 'undefined' && self.constructor === Window && typeof document === 'object' && document !== null && self.document === document && typeof location === 'object' && location !== null && self.location === location && typeof history === 'object' && history !== null && self.history === history && typeof navigator === 'object' && navigator !== null && self.navigator === navigator && typeof navigator.userAgent === 'string'; + _exports.hasDOM = hasDom; + var window = hasDom ? self : null; + _exports.window = window; + var location$1 = hasDom ? self.location : null; + _exports.location = location$1; + var history$1 = hasDom ? self.history : null; + _exports.history = history$1; + var userAgent = hasDom ? self.navigator.userAgent : 'Lynx (textmode)'; + _exports.userAgent = userAgent; + var isChrome = hasDom ? typeof chrome === 'object' && !(typeof opera === 'object') : false; + _exports.isChrome = isChrome; + var isFirefox = hasDom ? typeof InstallTrigger !== 'undefined' : false; + _exports.isFirefox = isFirefox; + var isIE = hasDom ? typeof MSInputMethodContext !== 'undefined' && typeof documentMode !== 'undefined' : false; + _exports.isIE = isIE; +}); +define("@ember/-internals/container/index", ["exports", "@ember/-internals/owner", "@ember/-internals/utils", "@ember/debug"], function (_exports, _owner, _utils, _debug) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.privatize = privatize; + _exports.getFactoryFor = getFactoryFor; + _exports.setFactoryFor = setFactoryFor; + _exports.INIT_FACTORY = _exports.Container = _exports.Registry = void 0; + var leakTracking; + var containers; + + if (true + /* DEBUG */ + ) { + // requires v8 + // chrome --js-flags="--allow-natives-syntax --expose-gc" + // node --allow-natives-syntax --expose-gc + try { + if (typeof gc === 'function') { + leakTracking = (() => { + // avoid syntax errors when --allow-natives-syntax not present + var GetWeakSetValues = new Function('weakSet', 'return %GetWeakSetValues(weakSet, 0)'); + containers = new WeakSet(); + return { + hasContainers() { + gc(); + return GetWeakSetValues(containers).length > 0; + }, + + reset() { + var values = GetWeakSetValues(containers); + + for (var i = 0; i < values.length; i++) { + containers.delete(values[i]); + } + } + + }; + })(); + } + } catch (e) {// ignore + } + } + /** + A container used to instantiate and cache objects. + + Every `Container` must be associated with a `Registry`, which is referenced + to determine the factory and options that should be used to instantiate + objects. + + The public API for `Container` is still in flux and should not be considered + stable. + + @private + @class Container + */ + + + class Container { + constructor(registry, options = {}) { + this.registry = registry; + this.owner = options.owner || null; + this.cache = (0, _utils.dictionary)(options.cache || null); + this.factoryManagerCache = (0, _utils.dictionary)(options.factoryManagerCache || null); + this.isDestroyed = false; + this.isDestroying = false; + + if (true + /* DEBUG */ + ) { + this.validationCache = (0, _utils.dictionary)(options.validationCache || null); + + if (containers !== undefined) { + containers.add(this); + } + } + } + /** + @private + @property registry + @type Registry + @since 1.11.0 + */ + + /** + @private + @property cache + @type InheritingDict + */ + + /** + @private + @property validationCache + @type InheritingDict + */ + + /** + Given a fullName return a corresponding instance. + The default behavior is for lookup to return a singleton instance. + The singleton is scoped to the container, allowing multiple containers + to all have their own locally scoped singletons. + ```javascript + let registry = new Registry(); + let container = registry.container(); + registry.register('api:twitter', Twitter); + let twitter = container.lookup('api:twitter'); + twitter instanceof Twitter; // => true + // by default the container will return singletons + let twitter2 = container.lookup('api:twitter'); + twitter2 instanceof Twitter; // => true + twitter === twitter2; //=> true + ``` + If singletons are not wanted, an optional flag can be provided at lookup. + ```javascript + let registry = new Registry(); + let container = registry.container(); + registry.register('api:twitter', Twitter); + let twitter = container.lookup('api:twitter', { singleton: false }); + let twitter2 = container.lookup('api:twitter', { singleton: false }); + twitter === twitter2; //=> false + ``` + @private + @method lookup + @param {String} fullName + @param {Object} [options] + @param {String} [options.source] The fullname of the request source (used for local lookup) + @return {any} + */ + + + lookup(fullName, options) { + if (this.isDestroyed) { + throw new Error(`Can not call \`.lookup\` after the owner has been destroyed`); + } + + (true && !(this.registry.isValidFullName(fullName)) && (0, _debug.assert)('fullName must be a proper full name', this.registry.isValidFullName(fullName))); + return lookup(this, this.registry.normalize(fullName), options); + } + /** + A depth first traversal, destroying the container, its descendant containers and all + their managed objects. + @private + @method destroy + */ + + + destroy() { + this.isDestroying = true; + destroyDestroyables(this); + } + + finalizeDestroy() { + resetCache(this); + this.isDestroyed = true; + } + /** + Clear either the entire cache or just the cache for a particular key. + @private + @method reset + @param {String} fullName optional key to reset; if missing, resets everything + */ + + + reset(fullName) { + if (this.isDestroyed) return; + + if (fullName === undefined) { + destroyDestroyables(this); + resetCache(this); + } else { + resetMember(this, this.registry.normalize(fullName)); + } + } + /** + Returns an object that can be used to provide an owner to a + manually created instance. + @private + @method ownerInjection + @returns { Object } + */ + + + ownerInjection() { + var injection = {}; + (0, _owner.setOwner)(injection, this.owner); + return injection; + } + /** + Given a fullName, return the corresponding factory. The consumer of the factory + is responsible for the destruction of any factory instances, as there is no + way for the container to ensure instances are destroyed when it itself is + destroyed. + @public + @method factoryFor + @param {String} fullName + @param {Object} [options] + @param {String} [options.source] The fullname of the request source (used for local lookup) + @return {any} + */ + + + factoryFor(fullName) { + if (this.isDestroyed) { + throw new Error(`Can not call \`.factoryFor\` after the owner has been destroyed`); + } + + var normalizedName = this.registry.normalize(fullName); + (true && !(this.registry.isValidFullName(normalizedName)) && (0, _debug.assert)('fullName must be a proper full name', this.registry.isValidFullName(normalizedName))); + return factoryFor(this, normalizedName, fullName); + } + + } + + _exports.Container = Container; + + if (true + /* DEBUG */ + ) { + Container._leakTracking = leakTracking; + } + /* + * Wrap a factory manager in a proxy which will not permit properties to be + * set on the manager. + */ + + + function wrapManagerInDeprecationProxy(manager) { + var validator = { + set(_obj, prop) { + throw new Error(`You attempted to set "${prop}" on a factory manager created by container#factoryFor. A factory manager is a read-only construct.`); + } + + }; // Note: + // We have to proxy access to the manager here so that private property + // access doesn't cause the above errors to occur. + + var m = manager; + var proxiedManager = { + class: m.class, + + create(props) { + return m.create(props); + } + + }; + return new Proxy(proxiedManager, validator); + } + + function isSingleton(container, fullName) { + return container.registry.getOption(fullName, 'singleton') !== false; + } + + function isInstantiatable(container, fullName) { + return container.registry.getOption(fullName, 'instantiate') !== false; + } + + function lookup(container, fullName, options = {}) { + var normalizedName = fullName; + + if (options.singleton === true || options.singleton === undefined && isSingleton(container, fullName)) { + var cached = container.cache[normalizedName]; + + if (cached !== undefined) { + return cached; + } + } + + return instantiateFactory(container, normalizedName, fullName, options); + } + + function factoryFor(container, normalizedName, fullName) { + var cached = container.factoryManagerCache[normalizedName]; + + if (cached !== undefined) { + return cached; + } + + var factory = container.registry.resolve(normalizedName); + + if (factory === undefined) { + return; + } + + if (true + /* DEBUG */ + && factory && typeof factory._onLookup === 'function') { + factory._onLookup(fullName); + } + + var manager = new FactoryManager(container, factory, fullName, normalizedName); + + if (true + /* DEBUG */ + ) { + manager = wrapManagerInDeprecationProxy(manager); + } + + container.factoryManagerCache[normalizedName] = manager; + return manager; + } + + function isSingletonClass(container, fullName, { + instantiate, + singleton + }) { + return singleton !== false && !instantiate && isSingleton(container, fullName) && !isInstantiatable(container, fullName); + } + + function isSingletonInstance(container, fullName, { + instantiate, + singleton + }) { + return singleton !== false && instantiate !== false && (singleton === true || isSingleton(container, fullName)) && isInstantiatable(container, fullName); + } + + function isFactoryClass(container, fullname, { + instantiate, + singleton + }) { + return instantiate === false && (singleton === false || !isSingleton(container, fullname)) && !isInstantiatable(container, fullname); + } + + function isFactoryInstance(container, fullName, { + instantiate, + singleton + }) { + return instantiate !== false && (singleton === false || !isSingleton(container, fullName)) && isInstantiatable(container, fullName); + } + + function instantiateFactory(container, normalizedName, fullName, options) { + var factoryManager = factoryFor(container, normalizedName, fullName); + + if (factoryManager === undefined) { + return; + } // SomeClass { singleton: true, instantiate: true } | { singleton: true } | { instantiate: true } | {} + // By default majority of objects fall into this case + + + if (isSingletonInstance(container, fullName, options)) { + var instance = container.cache[normalizedName] = factoryManager.create(); // if this lookup happened _during_ destruction (emits a deprecation, but + // is still possible) ensure that it gets destroyed + + if (container.isDestroying) { + if (typeof instance.destroy === 'function') { + instance.destroy(); + } + } + + return instance; + } // SomeClass { singleton: false, instantiate: true } + + + if (isFactoryInstance(container, fullName, options)) { + return factoryManager.create(); + } // SomeClass { singleton: true, instantiate: false } | { instantiate: false } | { singleton: false, instantiation: false } + + + if (isSingletonClass(container, fullName, options) || isFactoryClass(container, fullName, options)) { + return factoryManager.class; + } + + throw new Error('Could not create factory'); + } + + function destroyDestroyables(container) { + var cache = container.cache; + var keys = Object.keys(cache); + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var value = cache[key]; + + if (value.destroy) { + value.destroy(); + } + } + } + + function resetCache(container) { + container.cache = (0, _utils.dictionary)(null); + container.factoryManagerCache = (0, _utils.dictionary)(null); + } + + function resetMember(container, fullName) { + var member = container.cache[fullName]; + delete container.factoryManagerCache[fullName]; + + if (member) { + delete container.cache[fullName]; + + if (member.destroy) { + member.destroy(); + } + } + } + + var INIT_FACTORY = (0, _utils.symbol)('INIT_FACTORY'); + _exports.INIT_FACTORY = INIT_FACTORY; + + function getFactoryFor(obj) { + return obj[INIT_FACTORY]; + } + + function setFactoryFor(obj, factory) { + obj[INIT_FACTORY] = factory; + } + + class FactoryManager { + constructor(container, factory, fullName, normalizedName) { + this.container = container; + this.owner = container.owner; + this.class = factory; + this.fullName = fullName; + this.normalizedName = normalizedName; + this.madeToString = undefined; + this.injections = undefined; + setFactoryFor(this, this); + + if (isInstantiatable(container, fullName)) { + setFactoryFor(factory, this); + } + } + + toString() { + if (this.madeToString === undefined) { + this.madeToString = this.container.registry.makeToString(this.class, this.fullName); + } + + return this.madeToString; + } + + create(options) { + var { + container + } = this; + + if (container.isDestroyed) { + throw new Error(`Can not create new instances after the owner has been destroyed (you attempted to create ${this.fullName})`); + } + + var props = {}; + (0, _owner.setOwner)(props, container.owner); + setFactoryFor(props, this); + + if (options !== undefined) { + props = Object.assign({}, props, options); + } + + if (true + /* DEBUG */ + ) { + var lazyInjections; + var validationCache = this.container.validationCache; // Ensure that all lazy injections are valid at instantiation time + + if (!validationCache[this.fullName] && this.class && typeof this.class._lazyInjections === 'function') { + lazyInjections = this.class._lazyInjections(); + lazyInjections = this.container.registry.normalizeInjectionsHash(lazyInjections); + this.container.registry.validateInjections(lazyInjections); + } + + validationCache[this.fullName] = true; + (true && !(typeof this.class.create === 'function') && (0, _debug.assert)(`Failed to create an instance of '${this.normalizedName}'. Most likely an improperly defined class or an invalid module export.`, typeof this.class.create === 'function')); + } + + return this.class.create(props); + } + + } + + var VALID_FULL_NAME_REGEXP = /^[^:]+:[^:]+$/; + /** + A registry used to store factory and option information keyed + by type. + + A `Registry` stores the factory and option information needed by a + `Container` to instantiate and cache objects. + + The API for `Registry` is still in flux and should not be considered stable. + + @private + @class Registry + @since 1.11.0 + */ + + class Registry { + constructor(options = {}) { + this.fallback = options.fallback || null; + this.resolver = options.resolver || null; + this.registrations = (0, _utils.dictionary)(options.registrations || null); + this._localLookupCache = Object.create(null); + this._normalizeCache = (0, _utils.dictionary)(null); + this._resolveCache = (0, _utils.dictionary)(null); + this._failSet = new Set(); + this._options = (0, _utils.dictionary)(null); + this._typeOptions = (0, _utils.dictionary)(null); + } + /** + A backup registry for resolving registrations when no matches can be found. + @private + @property fallback + @type Registry + */ + + /** + An object that has a `resolve` method that resolves a name. + @private + @property resolver + @type Resolver + */ + + /** + @private + @property registrations + @type InheritingDict + */ + + /** + @private + @property _normalizeCache + @type InheritingDict + */ + + /** + @private + @property _resolveCache + @type InheritingDict + */ + + /** + @private + @property _options + @type InheritingDict + */ + + /** + @private + @property _typeOptions + @type InheritingDict + */ + + /** + Creates a container based on this registry. + @private + @method container + @param {Object} options + @return {Container} created container + */ + + + container(options) { + return new Container(this, options); + } + /** + Registers a factory for later injection. + Example: + ```javascript + let registry = new Registry(); + registry.register('model:user', Person, {singleton: false }); + registry.register('fruit:favorite', Orange); + registry.register('communication:main', Email, {singleton: false}); + ``` + @private + @method register + @param {String} fullName + @param {Function} factory + @param {Object} options + */ + + + register(fullName, factory, options = {}) { + (true && !(this.isValidFullName(fullName)) && (0, _debug.assert)('fullName must be a proper full name', this.isValidFullName(fullName))); + (true && !(factory !== undefined) && (0, _debug.assert)(`Attempting to register an unknown factory: '${fullName}'`, factory !== undefined)); + var normalizedName = this.normalize(fullName); + (true && !(!this._resolveCache[normalizedName]) && (0, _debug.assert)(`Cannot re-register: '${fullName}', as it has already been resolved.`, !this._resolveCache[normalizedName])); + + this._failSet.delete(normalizedName); + + this.registrations[normalizedName] = factory; + this._options[normalizedName] = options; + } + /** + Unregister a fullName + ```javascript + let registry = new Registry(); + registry.register('model:user', User); + registry.resolve('model:user').create() instanceof User //=> true + registry.unregister('model:user') + registry.resolve('model:user') === undefined //=> true + ``` + @private + @method unregister + @param {String} fullName + */ + + + unregister(fullName) { + (true && !(this.isValidFullName(fullName)) && (0, _debug.assert)('fullName must be a proper full name', this.isValidFullName(fullName))); + var normalizedName = this.normalize(fullName); + this._localLookupCache = Object.create(null); + delete this.registrations[normalizedName]; + delete this._resolveCache[normalizedName]; + delete this._options[normalizedName]; + + this._failSet.delete(normalizedName); + } + /** + Given a fullName return the corresponding factory. + By default `resolve` will retrieve the factory from + the registry. + ```javascript + let registry = new Registry(); + registry.register('api:twitter', Twitter); + registry.resolve('api:twitter') // => Twitter + ``` + Optionally the registry can be provided with a custom resolver. + If provided, `resolve` will first provide the custom resolver + the opportunity to resolve the fullName, otherwise it will fallback + to the registry. + ```javascript + let registry = new Registry(); + registry.resolver = function(fullName) { + // lookup via the module system of choice + }; + // the twitter factory is added to the module system + registry.resolve('api:twitter') // => Twitter + ``` + @private + @method resolve + @param {String} fullName + @param {Object} [options] + @param {String} [options.source] the fullname of the request source (used for local lookups) + @return {Function} fullName's factory + */ + + + resolve(fullName) { + var factory = resolve(this, this.normalize(fullName)); + + if (factory === undefined && this.fallback !== null) { + factory = this.fallback.resolve(...arguments); + } + + return factory; + } + /** + A hook that can be used to describe how the resolver will + attempt to find the factory. + For example, the default Ember `.describe` returns the full + class name (including namespace) where Ember's resolver expects + to find the `fullName`. + @private + @method describe + @param {String} fullName + @return {string} described fullName + */ + + + describe(fullName) { + if (this.resolver !== null && this.resolver.lookupDescription) { + return this.resolver.lookupDescription(fullName); + } else if (this.fallback !== null) { + return this.fallback.describe(fullName); + } else { + return fullName; + } + } + /** + A hook to enable custom fullName normalization behavior + @private + @method normalizeFullName + @param {String} fullName + @return {string} normalized fullName + */ + + + normalizeFullName(fullName) { + if (this.resolver !== null && this.resolver.normalize) { + return this.resolver.normalize(fullName); + } else if (this.fallback !== null) { + return this.fallback.normalizeFullName(fullName); + } else { + return fullName; + } + } + /** + Normalize a fullName based on the application's conventions + @private + @method normalize + @param {String} fullName + @return {string} normalized fullName + */ + + + normalize(fullName) { + return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this.normalizeFullName(fullName)); + } + /** + @method makeToString + @private + @param {any} factory + @param {string} fullName + @return {function} toString function + */ + + + makeToString(factory, fullName) { + var _a; + + if (this.resolver !== null && this.resolver.makeToString) { + return this.resolver.makeToString(factory, fullName); + } else if (this.fallback !== null) { + return this.fallback.makeToString(factory, fullName); + } else { + return typeof factory === 'string' ? factory : (_a = factory.name) !== null && _a !== void 0 ? _a : '(unknown class)'; + } + } + /** + Given a fullName check if the container is aware of its factory + or singleton instance. + @private + @method has + @param {String} fullName + @param {Object} [options] + @param {String} [options.source] the fullname of the request source (used for local lookups) + @return {Boolean} + */ + + + has(fullName) { + if (!this.isValidFullName(fullName)) { + return false; + } + + return has(this, this.normalize(fullName)); + } + /** + Allow registering options for all factories of a type. + ```javascript + let registry = new Registry(); + let container = registry.container(); + // if all of type `connection` must not be singletons + registry.optionsForType('connection', { singleton: false }); + registry.register('connection:twitter', TwitterConnection); + registry.register('connection:facebook', FacebookConnection); + let twitter = container.lookup('connection:twitter'); + let twitter2 = container.lookup('connection:twitter'); + twitter === twitter2; // => false + let facebook = container.lookup('connection:facebook'); + let facebook2 = container.lookup('connection:facebook'); + facebook === facebook2; // => false + ``` + @private + @method optionsForType + @param {String} type + @param {Object} options + */ + + + optionsForType(type, options) { + this._typeOptions[type] = options; + } + + getOptionsForType(type) { + var optionsForType = this._typeOptions[type]; + + if (optionsForType === undefined && this.fallback !== null) { + optionsForType = this.fallback.getOptionsForType(type); + } + + return optionsForType; + } + /** + @private + @method options + @param {String} fullName + @param {Object} options + */ + + + options(fullName, options) { + var normalizedName = this.normalize(fullName); + this._options[normalizedName] = options; + } + + getOptions(fullName) { + var normalizedName = this.normalize(fullName); + var options = this._options[normalizedName]; + + if (options === undefined && this.fallback !== null) { + options = this.fallback.getOptions(fullName); + } + + return options; + } + + getOption(fullName, optionName) { + var options = this._options[fullName]; + + if (options !== undefined && options[optionName] !== undefined) { + return options[optionName]; + } + + var type = fullName.split(':')[0]; + options = this._typeOptions[type]; + + if (options && options[optionName] !== undefined) { + return options[optionName]; + } else if (this.fallback !== null) { + return this.fallback.getOption(fullName, optionName); + } + + return undefined; + } + /** + This is deprecated in favor of explicit injection of dependencies. + Reference: https://deprecations.emberjs.com/v3.x#toc_implicit-injections + ``` + @private + @method injection + @param {String} factoryName + @param {String} property + @param {String} injectionName + @deprecated + */ + + + injection(fullName, property) { + (true && !(false) && (0, _debug.deprecate)(`As of Ember 4.0.0, owner.inject no longer injects values into resolved instances, and calling the method has been deprecated. Since this method no longer does anything, it is fully safe to remove this injection. As an alternative to this API, you can refactor to explicitly inject \`${property}\` on \`${fullName}\`, or look it up directly using the \`getOwner\` API.`, false, { + id: 'remove-owner-inject', + until: '5.0.0', + url: 'https://deprecations.emberjs.com/v4.x#toc_implicit-injections', + for: 'ember-source', + since: { + enabled: '4.0.0' + } + })); + } + /** + @private + @method knownForType + @param {String} type the type to iterate over + */ + + + knownForType(type) { + var localKnown = (0, _utils.dictionary)(null); + var registeredNames = Object.keys(this.registrations); + + for (var index = 0; index < registeredNames.length; index++) { + var fullName = registeredNames[index]; + var itemType = fullName.split(':')[0]; + + if (itemType === type) { + localKnown[fullName] = true; + } + } + + var fallbackKnown, resolverKnown; + + if (this.fallback !== null) { + fallbackKnown = this.fallback.knownForType(type); + } + + if (this.resolver !== null && this.resolver.knownForType) { + resolverKnown = this.resolver.knownForType(type); + } + + return Object.assign({}, fallbackKnown, localKnown, resolverKnown); + } + + isValidFullName(fullName) { + return VALID_FULL_NAME_REGEXP.test(fullName); + } + + } + + _exports.Registry = Registry; + + if (true + /* DEBUG */ + ) { + var proto = Registry.prototype; + + proto.normalizeInjectionsHash = function (hash) { + var injections = []; + + for (var key in hash) { + if (Object.prototype.hasOwnProperty.call(hash, key)) { + var { + specifier + } = hash[key]; + (true && !(this.isValidFullName(specifier)) && (0, _debug.assert)(`Expected a proper full name, given '${specifier}'`, this.isValidFullName(specifier))); + injections.push({ + property: key, + specifier + }); + } + } + + return injections; + }; + + proto.validateInjections = function (injections) { + if (!injections) { + return; + } + + for (var i = 0; i < injections.length; i++) { + var { + specifier + } = injections[i]; + (true && !(this.has(specifier)) && (0, _debug.assert)(`Attempting to inject an unknown injection: '${specifier}'`, this.has(specifier))); + } + }; + } + + function resolve(registry, _normalizedName) { + var normalizedName = _normalizedName; + var cached = registry._resolveCache[normalizedName]; + + if (cached !== undefined) { + return cached; + } + + if (registry._failSet.has(normalizedName)) { + return; + } + + var resolved; + + if (registry.resolver) { + resolved = registry.resolver.resolve(normalizedName); + } + + if (resolved === undefined) { + resolved = registry.registrations[normalizedName]; + } + + if (resolved === undefined) { + registry._failSet.add(normalizedName); + } else { + registry._resolveCache[normalizedName] = resolved; + } + + return resolved; + } + + function has(registry, fullName) { + return registry.resolve(fullName) !== undefined; + } + + var privateNames = (0, _utils.dictionary)(null); + var privateSuffix = `${Math.random()}${Date.now()}`.replace('.', ''); + + function privatize([fullName]) { + var name = privateNames[fullName]; + + if (name) { + return name; + } + + var [type, rawName] = fullName.split(':'); + return privateNames[fullName] = (0, _utils.intern)(`${type}:${rawName}-${privateSuffix}`); + } + /* + Public API for the container is still in flux. + The public API, specified on the application namespace should be considered the stable API. + // @module container + @private + */ + +}); +define("@ember/-internals/environment/index", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.getLookup = getLookup; + _exports.setLookup = setLookup; + _exports.getENV = getENV; + _exports.ENV = _exports.context = _exports.global = void 0; + + // from lodash to catch fake globals + function checkGlobal(value) { + return value && value.Object === Object ? value : undefined; + } // element ids can ruin global miss checks + + + function checkElementIdShadowing(value) { + return value && value.nodeType === undefined ? value : undefined; + } // export real global + + + var global$1 = checkGlobal(checkElementIdShadowing(typeof global === 'object' && global)) || checkGlobal(typeof self === 'object' && self) || checkGlobal(typeof window === 'object' && window) || typeof mainContext !== 'undefined' && mainContext || // set before strict mode in Ember loader/wrapper + new Function('return this')(); // eval outside of strict mode + + _exports.global = global$1; + + var context = function (global, Ember) { + return Ember === undefined ? { + imports: global, + exports: global, + lookup: global + } : { + // import jQuery + imports: Ember.imports || global, + // export Ember + exports: Ember.exports || global, + // search for Namespaces + lookup: Ember.lookup || global + }; + }(global$1, global$1.Ember); + + _exports.context = context; + + function getLookup() { + return context.lookup; + } + + function setLookup(value) { + context.lookup = value; + } + /** + The hash of environment variables used to control various configuration + settings. To specify your own or override default settings, add the + desired properties to a global hash named `EmberENV` (or `ENV` for + backwards compatibility with earlier versions of Ember). The `EmberENV` + hash must be created before loading Ember. + + @class EmberENV + @type Object + @public + */ + + + var ENV = { + ENABLE_OPTIONAL_FEATURES: false, + + /** + Determines whether Ember should add to `Array` + native object prototypes, a few extra methods in order to provide a more + friendly API. + We generally recommend leaving this option set to true however, if you need + to turn it off, you can add the configuration property + `EXTEND_PROTOTYPES` to `EmberENV` and set it to `false`. + Note, when disabled (the default configuration for Ember Addons), you will + instead have to access all methods and functions from the Ember + namespace. + @property EXTEND_PROTOTYPES + @type Boolean + @default true + @for EmberENV + @public + */ + EXTEND_PROTOTYPES: { + Array: true + }, + + /** + The `LOG_STACKTRACE_ON_DEPRECATION` property, when true, tells Ember to log + a full stack trace during deprecation warnings. + @property LOG_STACKTRACE_ON_DEPRECATION + @type Boolean + @default true + @for EmberENV + @public + */ + LOG_STACKTRACE_ON_DEPRECATION: true, + + /** + The `LOG_VERSION` property, when true, tells Ember to log versions of all + dependent libraries in use. + @property LOG_VERSION + @type Boolean + @default true + @for EmberENV + @public + */ + LOG_VERSION: true, + RAISE_ON_DEPRECATION: false, + STRUCTURED_PROFILE: false, + + /** + Whether to insert a `
` wrapper around the + application template. See RFC #280. + This is not intended to be set directly, as the implementation may change in + the future. Use `@ember/optional-features` instead. + @property _APPLICATION_TEMPLATE_WRAPPER + @for EmberENV + @type Boolean + @default true + @private + */ + _APPLICATION_TEMPLATE_WRAPPER: true, + + /** + Whether to use Glimmer Component semantics (as opposed to the classic "Curly" + components semantics) for template-only components. See RFC #278. + This is not intended to be set directly, as the implementation may change in + the future. Use `@ember/optional-features` instead. + @property _TEMPLATE_ONLY_GLIMMER_COMPONENTS + @for EmberENV + @type Boolean + @default false + @private + */ + _TEMPLATE_ONLY_GLIMMER_COMPONENTS: false, + + /** + Whether to perform extra bookkeeping needed to make the `captureRenderTree` + API work. + This has to be set before the ember JavaScript code is evaluated. This is + usually done by setting `window.EmberENV = { _DEBUG_RENDER_TREE: true };` + before the "vendor" `'; + checkTemplate('funkyTemplate', assert); + } + + ['@test template with id instead of data-template-name should add a new template to Ember.TEMPLATES'](assert) { + fixture.innerHTML = ''; + checkTemplate('funkyTemplate', assert); + } + + ['@test template without data-template-name or id should default to application'](assert) { + fixture.innerHTML = ''; + checkTemplate('application', assert); + } // Add this test case, only for typeof Handlebars === 'object'; + + + [`${typeof Handlebars === 'object' ? '@test' : '@skip'} template with type text/x-raw-handlebars should be parsed`](assert) { + fixture.innerHTML = ''; + (0, _runloop.run)(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + })); + var template = (0, _glimmer.getTemplate)('funkyTemplate'); + assert.ok(template, 'template with name funkyTemplate available'); // This won't even work with Ember templates + + assert.equal(template({ + name: 'Tobias' + }).trim(), 'Tobias'); + } + + ['@test duplicated default application templates should throw exception'](assert) { + fixture.innerHTML = ''; + assert.throws(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + }), /Template named "[^"]+" already exists\./, 'duplicate templates should not be allowed'); + } + + ['@test default default application template and id application template present should throw exception'](assert) { + fixture.innerHTML = ''; + assert.throws(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + }), /Template named "[^"]+" already exists\./, 'duplicate templates should not be allowed'); + } + + ['@test default application template and data-template-name application template present should throw exception'](assert) { + fixture.innerHTML = ''; + assert.throws(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + }), /Template named "[^"]+" already exists\./, 'duplicate templates should not be allowed'); + } + + ['@test duplicated template id should throw exception'](assert) { + fixture.innerHTML = ''; + assert.throws(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + }), /Template named "[^"]+" already exists\./, 'duplicate templates should not be allowed'); + } + + ['@test duplicated template data-template-name should throw exception'](assert) { + fixture.innerHTML = ''; + assert.throws(() => (0, _bootstrap.default)({ + context: fixture, + hasTemplate: _glimmer.hasTemplate, + setTemplate: _glimmer.setTemplate + }), /Template named "[^"]+" already exists\./, 'duplicate templates should not be allowed'); + } + + }); +}); +define("ember-template-compiler/tests/system/compile_options_test", ["ember-template-compiler/index", "internal-test-helpers"], function (_index, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('ember-template-compiler: default compile options', class extends _internalTestHelpers.AbstractTestCase { + ['@test default options are a new copy'](assert) { + assert.notEqual((0, _index.compileOptions)(), (0, _index.compileOptions)()); + } + + ['@test customizeComponentName asserts name is well formed'](assert) { + var options = (0, _index.compileOptions)({ + moduleName: 'test.js' + }); + expectAssertion(() => { + options.customizeComponentName('Foo:Bar'); + }, /You tried to invoke a component named in "test.js", but that is not a valid name for a component. Did you mean to use the "::" syntax for nested components\?/); + assert.ok(options.customizeComponentName('Foo::Bar')); + } + + ['@test has default AST plugins in resolution mode'](assert) { + assert.expect(_index.RESOLUTION_MODE_TRANSFORMS.length); + var plugins = (0, _index.compileOptions)().plugins.ast; + + for (var i = 0; i < _index.RESOLUTION_MODE_TRANSFORMS.length; i++) { + var plugin = _index.RESOLUTION_MODE_TRANSFORMS[i]; + assert.ok(plugins.indexOf(plugin) > -1, `includes ${plugin}`); + } + } + + ['@test has default AST plugins in strict mode'](assert) { + assert.expect(_index.STRICT_MODE_TRANSFORMS.length); + var plugins = (0, _index.compileOptions)({ + strictMode: true + }).plugins.ast; + + for (var i = 0; i < _index.STRICT_MODE_TRANSFORMS.length; i++) { + var plugin = _index.STRICT_MODE_TRANSFORMS[i]; + assert.ok(plugins.indexOf(plugin) > -1, `includes ${plugin}`); + } + } + + }); + + function customTransform() { + return { + name: 'remove-data-test', + visitor: { + ElementNode(node) { + for (var i = 0; i < node.attributes.length; i++) { + var attribute = node.attributes[i]; + + if (attribute.name === 'data-test') { + node.attributes.splice(i, 1); + } + } + } + + } + }; + } + + (0, _internalTestHelpers.moduleFor)('ember-template-compiler: custom plugins passed to compile', class extends _internalTestHelpers.RenderingTestCase { + // override so that we can provide custom AST plugins to compile + compile(templateString) { + return (0, _index.compile)(templateString, { + plugins: { + ast: [customTransform] + } + }); + } + + }); +}); +define("ember-template-compiler/tests/system/dasherize-component-name-test", ["ember-template-compiler/lib/system/dasherize-component-name", "internal-test-helpers"], function (_dasherizeComponentName, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('dasherize-component-name', class extends _internalTestHelpers.AbstractTestCase { + ['@test names are correctly dasherized'](assert) { + assert.equal(_dasherizeComponentName.default.get('Foo'), 'foo'); + assert.equal(_dasherizeComponentName.default.get('foo-bar'), 'foo-bar'); + assert.equal(_dasherizeComponentName.default.get('FooBar'), 'foo-bar'); + assert.equal(_dasherizeComponentName.default.get('F3Bar'), 'f3-bar'); + assert.equal(_dasherizeComponentName.default.get('Foo3Bar'), 'foo3-bar'); + assert.equal(_dasherizeComponentName.default.get('Foo3barBaz'), 'foo3bar-baz'); + assert.equal(_dasherizeComponentName.default.get('FooB3ar'), 'foo-b3ar'); + assert.equal(_dasherizeComponentName.default.get('XBlah'), 'x-blah'); + assert.equal(_dasherizeComponentName.default.get('X-Blah'), 'x-blah'); + assert.equal(_dasherizeComponentName.default.get('Foo@BarBaz'), 'foo@bar-baz'); + assert.equal(_dasherizeComponentName.default.get('Foo@Bar-Baz'), 'foo@bar-baz'); + assert.equal(_dasherizeComponentName.default.get('Foo::BarBaz'), 'foo/bar-baz'); + assert.equal(_dasherizeComponentName.default.get('Foo::Bar-Baz'), 'foo/bar-baz'); + assert.equal(_dasherizeComponentName.default.get('Foo::BarBaz::Bang'), 'foo/bar-baz/bang'); + } + + }); +}); +define("ember-template-compiler/tests/utils/transform-test-case", ["exports", "@glimmer/compiler", "internal-test-helpers", "ember-template-compiler/index"], function (_exports, _compiler, _internalTestHelpers, _index) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class _default extends _internalTestHelpers.AbstractTestCase { + assertTransformed(before, after) { + this.assert.deepEqual(deloc(ast(before)), deloc(ast(after))); + } + + } + + _exports.default = _default; + + function ast(template) { + var _a; + + var program = null; + + function extractProgram() { + return { + name: 'extract-program', + visitor: { + Program: { + exit(node) { + program = clone(node); + } + + } + } + }; + } + + var options = (0, _index.compileOptions)({ + moduleName: '-top-level' + }); + + if ((_a = options.plugins) === null || _a === void 0 ? void 0 : _a.ast) { + options.plugins.ast.push(extractProgram); + } + + (0, _compiler.precompile)(template, options); + return program; + } + + function clone(node) { + var out = Object.create(null); + var keys = Object.keys(node); + keys.forEach(key => { + var value = node[key]; + + if (value !== null && typeof value === 'object') { + out[key] = clone(value); + } else { + out[key] = value; + } + }); + return out; + } + + function deloc(node) { + var out = Object.create(null); + var keys = Object.keys(node); + keys.forEach(key => { + var value = node[key]; + + if (key === 'loc') { + return; + } else if (value !== null && typeof value === 'object') { + out[key] = deloc(value); + } else { + out[key] = value; + } + }); + return out; + } +}); +define("ember-testing/tests/adapters/adapter_test", ["@ember/runloop", "ember-testing/lib/adapters/adapter", "internal-test-helpers"], function (_runloop, _adapter, _internalTestHelpers) { + "use strict"; + + var adapter; + (0, _internalTestHelpers.moduleFor)('ember-testing Adapter', class extends _internalTestHelpers.AbstractTestCase { + constructor() { + super(); + adapter = _adapter.default.create(); + } + + teardown() { + (0, _runloop.run)(adapter, adapter.destroy); + } + + ['@test exception throws'](assert) { + var error = 'Hai'; + var thrown; + + try { + adapter.exception(error); + } catch (e) { + thrown = e; + } + + assert.equal(thrown, error); + } + + }); +}); +define("ember-testing/tests/adapters/qunit_test", ["@ember/runloop", "ember-testing/lib/adapters/qunit", "internal-test-helpers"], function (_runloop, _qunit, _internalTestHelpers) { + "use strict"; + + var adapter; + (0, _internalTestHelpers.moduleFor)('ember-testing QUnitAdapter: QUnit 2.x', class extends _internalTestHelpers.AbstractTestCase { + constructor() { + super(); + this.originalStart = QUnit.start; + this.originalStop = QUnit.stop; + delete QUnit.start; + delete QUnit.stop; + adapter = _qunit.default.create(); + } + + teardown() { + (0, _runloop.run)(adapter, adapter.destroy); + QUnit.start = this.originalStart; + QUnit.stop = this.originalStop; + } + + ['@test asyncStart waits for asyncEnd to finish a test'](assert) { + adapter.asyncStart(); + setTimeout(function () { + assert.ok(true); + adapter.asyncEnd(); + }, 50); + } + + ['@test asyncStart waits for equal numbers of asyncEnd to finish a test'](assert) { + var adapter = _qunit.default.create(); + + adapter.asyncStart(); + adapter.asyncStart(); + adapter.asyncEnd(); + setTimeout(function () { + assert.ok(true); + adapter.asyncEnd(); + }, 50); + } + + }); +}); +define("ember-testing/tests/adapters_test", ["@ember/runloop", "@ember/-internals/error-handling", "ember-testing/lib/test", "ember-testing/lib/adapters/adapter", "ember-testing/lib/adapters/qunit", "@ember/application", "internal-test-helpers", "@ember/-internals/runtime", "@ember/debug"], function (_runloop, _errorHandling, _test, _adapter, _qunit, _application, _internalTestHelpers, _runtime, _debug) { + "use strict"; + + var HAS_UNHANDLED_REJECTION_HANDLER = ('onunhandledrejection' in window); + var originalDebug = (0, _debug.getDebugFunction)('debug'); + + var noop = function () {}; + + var App, originalAdapter, originalQUnit, originalWindowOnerror, originalQUnitUnhandledRejection; + var originalConsoleError = console.error; // eslint-disable-line no-console + + function runThatThrowsSync(message = 'Error for testing error handling') { + return (0, _runloop.run)(() => { + throw new Error(message); + }); + } + + function runThatThrowsAsync(message = 'Error for testing error handling') { + return (0, _runloop.next)(() => { + throw new Error(message); + }); + } + + class AdapterSetupAndTearDown extends _internalTestHelpers.AbstractTestCase { + constructor() { + (0, _debug.setDebugFunction)('debug', noop); + super(); + originalAdapter = _test.default.adapter; + originalQUnit = QUnit; + originalWindowOnerror = window.onerror; + originalQUnitUnhandledRejection = QUnit.onUnhandledRejection; + } + + afterEach() { + super.afterEach(); + (0, _debug.setDebugFunction)('debug', originalDebug); + + if (App) { + (0, _runloop.run)(App, App.destroy); + App.removeTestHelpers(); + App = null; + } + + _test.default.adapter = originalAdapter; + window.QUnit = originalQUnit; + window.onerror = originalWindowOnerror; + (0, _errorHandling.setOnerror)(undefined); + console.error = originalConsoleError; // eslint-disable-line no-console + + QUnit.onUnhandledRejection = originalQUnitUnhandledRejection; + } + + } + + (0, _internalTestHelpers.moduleFor)('ember-testing Adapters', class extends AdapterSetupAndTearDown { + ['@test Setting a test adapter manually'](assert) { + assert.expect(1); + var CustomAdapter; + CustomAdapter = _adapter.default.extend({ + asyncStart() { + assert.ok(true, 'Correct adapter was used'); + } + + }); + (0, _runloop.run)(function () { + App = _application.default.create({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + _test.default.adapter = CustomAdapter.create(); + App.setupForTesting(); + }); + + _test.default.adapter.asyncStart(); + } + + ['@test QUnitAdapter is used by default (if QUnit is available)'](assert) { + assert.expect(1); + _test.default.adapter = null; + (0, _runloop.run)(function () { + App = _application.default.create({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + App.setupForTesting(); + }); + assert.ok(_test.default.adapter instanceof _qunit.default); + } + + ['@test Adapter is used by default (if QUnit is not available)'](assert) { + assert.expect(2); + delete window.QUnit; + _test.default.adapter = null; + (0, _runloop.run)(function () { + App = _application.default.create({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + App.setupForTesting(); + }); + assert.ok(_test.default.adapter instanceof _adapter.default); + assert.ok(!(_test.default.adapter instanceof _qunit.default)); + } + + ['@test With Ember.Test.adapter set, errors in synchronous Ember.run are bubbled out'](assert) { + var thrown = new Error('Boom!'); + var caughtInAdapter, caughtInCatch; + _test.default.adapter = _qunit.default.create({ + exception(error) { + caughtInAdapter = error; + } + + }); + + try { + (0, _runloop.run)(() => { + throw thrown; + }); + } catch (e) { + caughtInCatch = e; + } + + assert.equal(caughtInAdapter, undefined, 'test adapter should never receive synchronous errors'); + assert.equal(caughtInCatch, thrown, 'a "normal" try/catch should catch errors in sync run'); + } + + ['@test when both Ember.onerror (which rethrows) and TestAdapter are registered - sync run'](assert) { + assert.expect(2); + _test.default.adapter = { + exception() { + assert.notOk(true, 'adapter is not called for errors thrown in sync run loops'); + } + + }; + (0, _errorHandling.setOnerror)(function (error) { + assert.ok(true, 'onerror is called for sync errors even if TestAdapter is setup'); + throw error; + }); + assert.throws(runThatThrowsSync, Error, 'error is thrown'); + } + + ['@test when both Ember.onerror (which does not rethrow) and TestAdapter are registered - sync run'](assert) { + assert.expect(2); + _test.default.adapter = { + exception() { + assert.notOk(true, 'adapter is not called for errors thrown in sync run loops'); + } + + }; + (0, _errorHandling.setOnerror)(function () { + assert.ok(true, 'onerror is called for sync errors even if TestAdapter is setup'); + }); + runThatThrowsSync(); + assert.ok(true, 'no error was thrown, Ember.onerror can intercept errors'); + } + + ['@test when TestAdapter is registered and error is thrown - async run'](assert) { + assert.expect(3); + var done = assert.async(); + var caughtInAdapter, caughtInCatch, caughtByWindowOnerror; + _test.default.adapter = { + exception(error) { + caughtInAdapter = error; + } + + }; + + window.onerror = function (message) { + caughtByWindowOnerror = message; // prevent "bubbling" and therefore failing the test + + return true; + }; + + try { + runThatThrowsAsync(); + } catch (e) { + caughtInCatch = e; + } + + setTimeout(() => { + assert.equal(caughtInAdapter, undefined, 'test adapter should never catch errors in run loops'); + assert.equal(caughtInCatch, undefined, 'a "normal" try/catch should never catch errors in an async run'); + assert.pushResult({ + result: /Error for testing error handling/.test(caughtByWindowOnerror), + actual: caughtByWindowOnerror, + expected: 'to include `Error for testing error handling`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + done(); + }, 20); + } + + ['@test when both Ember.onerror and TestAdapter are registered - async run'](assert) { + assert.expect(1); + var done = assert.async(); + _test.default.adapter = { + exception() { + assert.notOk(true, 'Adapter.exception is not called for errors thrown in next'); + } + + }; + (0, _errorHandling.setOnerror)(function () { + assert.ok(true, 'onerror is invoked for errors thrown in next/later'); + }); + runThatThrowsAsync(); + setTimeout(done, 10); + } + + }); + + function testAdapter(message, generatePromise, timeout = 10) { + return class PromiseFailureTests extends AdapterSetupAndTearDown { + [`@test ${message} when TestAdapter without \`exception\` method is present - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(1); + var thrown = new Error('the error'); + _test.default.adapter = _qunit.default.create({ + exception: undefined + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (rejection) { + assert.pushResult({ + result: /the error/.test(rejection.reason), + actual: rejection.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); // prevent "bubbling" and therefore failing the test + + return true; + }; + + generatePromise(thrown); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _runtime.RSVP.Promise(resolve => setTimeout(resolve, timeout)); + } + + [`@test ${message} when both Ember.onerror and TestAdapter without \`exception\` method are present - rsvp`](assert) { + assert.expect(1); + var thrown = new Error('the error'); + _test.default.adapter = _qunit.default.create({ + exception: undefined + }); + (0, _errorHandling.setOnerror)(function (error) { + assert.pushResult({ + result: /the error/.test(error.message), + actual: error.message, + expected: 'to include `the error`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + }); + generatePromise(thrown); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _runtime.RSVP.Promise(resolve => setTimeout(resolve, timeout)); + } + + [`@test ${message} when TestAdapter is present - rsvp`](assert) { + assert.expect(1); + + console.error = () => {}; // eslint-disable-line no-console + + + var thrown = new Error('the error'); + _test.default.adapter = _qunit.default.create({ + exception(error) { + assert.strictEqual(error, thrown, 'Adapter.exception is called for errors thrown in RSVP promises'); + } + + }); + generatePromise(thrown); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _runtime.RSVP.Promise(resolve => setTimeout(resolve, timeout)); + } + + [`@test ${message} when both Ember.onerror and TestAdapter are present - rsvp`](assert) { + assert.expect(1); + var thrown = new Error('the error'); + _test.default.adapter = _qunit.default.create({ + exception(error) { + assert.strictEqual(error, thrown, 'Adapter.exception is called for errors thrown in RSVP promises'); + } + + }); + (0, _errorHandling.setOnerror)(function () { + assert.notOk(true, 'Ember.onerror is not called if Test.adapter does not rethrow'); + }); + generatePromise(thrown); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _runtime.RSVP.Promise(resolve => setTimeout(resolve, timeout)); + } + + [`@test ${message} when both Ember.onerror and TestAdapter are present - rsvp`](assert) { + assert.expect(2); + var thrown = new Error('the error'); + _test.default.adapter = _qunit.default.create({ + exception(error) { + assert.strictEqual(error, thrown, 'Adapter.exception is called for errors thrown in RSVP promises'); + throw error; + } + + }); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises if Test.adapter rethrows'); + }); + generatePromise(thrown); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _runtime.RSVP.Promise(resolve => setTimeout(resolve, timeout)); + } + + }; + } + + (0, _internalTestHelpers.moduleFor)('Adapter Errors: .then callback', testAdapter('errors in promise constructor', error => { + new _runtime.RSVP.Promise(() => { + throw error; + }); + })); + (0, _internalTestHelpers.moduleFor)('Adapter Errors: Promise Contructor', testAdapter('errors in promise constructor', error => { + _runtime.RSVP.resolve().then(() => { + throw error; + }); + })); + (0, _internalTestHelpers.moduleFor)('Adapter Errors: Promise chain .then callback', testAdapter('errors in promise constructor', error => { + new _runtime.RSVP.Promise(resolve => setTimeout(resolve, 10)).then(() => { + throw error; + }); + }, 20)); +}); +define("ember-testing/tests/ext/rsvp_test", ["ember-testing/lib/ext/rsvp", "ember-testing/lib/test/adapter", "ember-testing/lib/test/promise", "@ember/runloop", "@ember/debug", "internal-test-helpers"], function (_rsvp, _adapter, _promise, _runloop, _debug, _internalTestHelpers) { + "use strict"; + + var originalTestAdapter = (0, _adapter.getAdapter)(); + var originalTestingFlag = (0, _debug.isTesting)(); + var asyncStarted = 0; + var asyncEnded = 0; + (0, _internalTestHelpers.moduleFor)('ember-testing RSVP', class extends _internalTestHelpers.AbstractTestCase { + constructor() { + super(); + (0, _debug.setTesting)(true); + (0, _adapter.setAdapter)({ + asyncStart() { + asyncStarted++; + }, + + asyncEnd() { + asyncEnded++; + } + + }); + } + + teardown() { + asyncStarted = 0; + asyncEnded = 0; + (0, _adapter.setAdapter)(originalTestAdapter); + (0, _debug.setTesting)(originalTestingFlag); + } + + ['@test given `Ember.testing = true`, correctly informs the test suite about async steps'](assert) { + var done = assert.async(); + assert.expect(19); + assert.ok(!(0, _runloop._getCurrentRunLoop)(), 'expect no run-loop'); + (0, _debug.setTesting)(true); + assert.equal(asyncStarted, 0); + assert.equal(asyncEnded, 0); + + var user = _rsvp.default.Promise.resolve({ + name: 'tomster' + }); + + assert.equal(asyncStarted, 0); + assert.equal(asyncEnded, 0); + user.then(function (user) { + assert.equal(asyncStarted, 1); + assert.equal(asyncEnded, 1); + assert.equal(user.name, 'tomster'); + return _rsvp.default.Promise.resolve(1).then(function () { + assert.equal(asyncStarted, 1); + assert.equal(asyncEnded, 1); + }); + }).then(function () { + assert.equal(asyncStarted, 1); + assert.equal(asyncEnded, 1); + return new _rsvp.default.Promise(function (resolve) { + setTimeout(function () { + assert.equal(asyncStarted, 1); + assert.equal(asyncEnded, 1); + resolve({ + name: 'async tomster' + }); + assert.equal(asyncStarted, 2); + assert.equal(asyncEnded, 1); + }, 0); + }); + }).then(function (user) { + assert.equal(user.name, 'async tomster'); + assert.equal(asyncStarted, 2); + assert.equal(asyncEnded, 2); + done(); + }); + } + + }); + (0, _internalTestHelpers.moduleFor)('TestPromise', class extends _internalTestHelpers.AbstractTestCase { + ['does not throw error when falsy value passed to then'](assert) { + assert.expect(1); + return new _promise.default(function (resolve) { + resolve(); + }).then(null).then(function () { + assert.ok(true); + }); + } + + ['able to get last Promise'](assert) { + assert.expect(2); + var p1 = new _promise.default(function (resolve) { + resolve(); + }).then(function () { + assert.ok(true); + }); + var p2 = new _promise.default(function (resolve) { + resolve(); + }); + assert.deepEqual((0, _promise.getLastPromise)(), p2); + return p1; + } + + }); +}); +define("ember-testing/tests/helper_registration_test", ["@ember/runloop", "ember-testing/lib/test", "@ember/application", "internal-test-helpers"], function (_runloop, _test, _application, _internalTestHelpers) { + "use strict"; + + var App, appBooted, helperContainer; + + function registerHelper() { + _test.default.registerHelper('boot', function (app) { + (0, _runloop.run)(app, app.advanceReadiness); + appBooted = true; + return app.testHelpers.wait(); + }); + } + + function unregisterHelper() { + _test.default.unregisterHelper('boot'); + } + + var originalAdapter = _test.default.adapter; + + function setupApp() { + appBooted = false; + helperContainer = {}; + (0, _runloop.run)(function () { + App = _application.default.create({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + App.setupForTesting(); + App.injectTestHelpers(helperContainer); + }); + } + + function destroyApp() { + if (App) { + (0, _runloop.run)(App, 'destroy'); + App = null; + helperContainer = null; + } + } + + (0, _internalTestHelpers.moduleFor)('Test - registerHelper/unregisterHelper', class extends _internalTestHelpers.AbstractTestCase { + teardown() { + _test.default.adapter = originalAdapter; + destroyApp(); + } + + ['@test Helper gets registered'](assert) { + assert.expect(2); + registerHelper(); + setupApp(); + assert.ok(App.testHelpers.boot); + assert.ok(helperContainer.boot); + } + + ['@test Helper is ran when called'](assert) { + var done = assert.async(); + assert.expect(1); + registerHelper(); + setupApp(); + App.testHelpers.boot().then(function () { + assert.ok(appBooted); + }).finally(done); + } + + ['@test Helper can be unregistered'](assert) { + assert.expect(4); + registerHelper(); + setupApp(); + assert.ok(App.testHelpers.boot); + assert.ok(helperContainer.boot); + unregisterHelper(); + (0, _runloop.run)(App, 'destroy'); + setupApp(); + assert.ok(!App.testHelpers.boot, 'once unregistered the helper is not added to App.testHelpers'); + assert.ok(!helperContainer.boot, 'once unregistered the helper is not added to the helperContainer'); + } + + }); +}); +define("ember-testing/tests/reexports_test", ["ember", "internal-test-helpers"], function (_ember, _internalTestHelpers) { + "use strict"; + + class ReexportsTestCase extends _internalTestHelpers.AbstractTestCase {} + + [// ember-testing + ['Test', 'ember-testing'], ['Test.Adapter', 'ember-testing', 'Adapter'], ['Test.QUnitAdapter', 'ember-testing', 'QUnitAdapter'], ['setupForTesting', 'ember-testing']].forEach(reexport => { + var [path, moduleId, exportName] = reexport; // default path === exportName if none present + + if (!exportName) { + exportName = path; + } + + ReexportsTestCase.prototype[`@test Ember.${path} exports correctly`] = function (assert) { + (0, _internalTestHelpers.confirmExport)(_ember.default, assert, path, moduleId, exportName); + }; + }); + (0, _internalTestHelpers.moduleFor)('ember-testing reexports', ReexportsTestCase); +}); +define("ember-testing/tests/test/waiters-test", ["ember-testing/lib/test/waiters", "internal-test-helpers"], function (_waiters, _internalTestHelpers) { + "use strict"; + + class Waiters { + constructor() { + this._waiters = []; + } + + add() { + this._waiters.push([...arguments]); + } + + register() { + this.forEach((...args) => { + (0, _waiters.registerWaiter)(...args); + }); + } + + unregister() { + this.forEach((...args) => { + (0, _waiters.unregisterWaiter)(...args); + }); + } + + forEach(callback) { + for (var i = 0; i < this._waiters.length; i++) { + var args = this._waiters[i]; + callback(...args); + } + } + + check() { + this.register(); + var result = (0, _waiters.checkWaiters)(); + this.unregister(); + return result; + } + + } + + (0, _internalTestHelpers.moduleFor)('ember-testing: waiters', class extends _internalTestHelpers.AbstractTestCase { + constructor() { + super(); + this.waiters = new Waiters(); + } + + teardown() { + this.waiters.unregister(); + } + + ['@test registering a waiter'](assert) { + assert.expect(2); + var obj = { + foo: true + }; + this.waiters.add(obj, function () { + assert.ok(this.foo, 'has proper `this` context'); + return true; + }); + this.waiters.add(function () { + assert.ok(true, 'is called'); + return true; + }); + this.waiters.check(); + } + + ['@test unregistering a waiter'](assert) { + assert.expect(2); + var obj = { + foo: true + }; + this.waiters.add(obj, function () { + assert.ok(true, 'precond - waiter with context is registered'); + return true; + }); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter without context is registered'); + return true; + }); + this.waiters.check(); + this.waiters.unregister(); + (0, _waiters.checkWaiters)(); + } + + ['@test checkWaiters returns false if all waiters return true'](assert) { + assert.expect(3); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter is registered'); + return true; + }); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter is registered'); + return true; + }); + assert.notOk(this.waiters.check(), 'checkWaiters returns true if all waiters return true'); + } + + ['@test checkWaiters returns true if any waiters return false'](assert) { + assert.expect(3); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter is registered'); + return true; + }); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter is registered'); + return false; + }); + assert.ok(this.waiters.check(), 'checkWaiters returns false if any waiters return false'); + } + + ['@test checkWaiters short circuits after first falsey waiter'](assert) { + assert.expect(2); + this.waiters.add(function () { + assert.ok(true, 'precond - waiter is registered'); + return false; + }); + this.waiters.add(function () { + assert.notOk(true, 'waiter should not be called'); + }); + assert.ok(this.waiters.check(), 'checkWaiters returns false if any waiters return false'); + } + + }); +}); +define("ember/tests/application_lifecycle_test", ["internal-test-helpers", "@ember/application", "@ember/-internals/routing", "@ember/-internals/glimmer", "@ember/debug"], function (_internalTestHelpers, _application, _routing, _glimmer, _debug) { + "use strict"; + + var originalDebug = (0, _debug.getDebugFunction)('debug'); + + var noop = function () {}; + + (0, _internalTestHelpers.moduleFor)('Application Lifecycle - route hooks', class extends _internalTestHelpers.AutobootApplicationTestCase { + createApplication() { + var application = super.createApplication(...arguments); + this.add('router:main', _routing.Router.extend({ + location: 'none' + })); + return application; + } + + constructor() { + (0, _debug.setDebugFunction)('debug', noop); + super(); + var menuItem = this.menuItem = {}; + (0, _internalTestHelpers.runTask)(() => { + this.createApplication(); + + var SettingRoute = _routing.Route.extend({ + setupController() { + this.controller.set('selectedMenuItem', menuItem); + }, + + deactivate() { + this.controller.set('selectedMenuItem', null); + } + + }); + + this.add('route:index', SettingRoute); + this.add('route:application', SettingRoute); + }); + } + + teardown() { + (0, _debug.setDebugFunction)('debug', originalDebug); + } + + get indexController() { + return this.applicationInstance.lookup('controller:index'); + } + + get applicationController() { + return this.applicationInstance.lookup('controller:application'); + } + + [`@test Resetting the application allows controller properties to be set when a route deactivates`](assert) { + var { + indexController, + applicationController + } = this; + assert.equal(indexController.get('selectedMenuItem'), this.menuItem); + assert.equal(applicationController.get('selectedMenuItem'), this.menuItem); + this.application.reset(); + assert.equal(indexController.get('selectedMenuItem'), null); + assert.equal(applicationController.get('selectedMenuItem'), null); + } + + [`@test Destroying the application resets the router before the appInstance is destroyed`](assert) { + var { + indexController, + applicationController + } = this; + assert.equal(indexController.get('selectedMenuItem'), this.menuItem); + assert.equal(applicationController.get('selectedMenuItem'), this.menuItem); + (0, _internalTestHelpers.runTask)(() => { + this.application.destroy(); + }); + assert.equal(indexController.get('selectedMenuItem'), null); + assert.equal(applicationController.get('selectedMenuItem'), null); + } + + }); + (0, _internalTestHelpers.moduleFor)('Application Lifecycle', class extends _internalTestHelpers.AutobootApplicationTestCase { + createApplication() { + var application = super.createApplication(...arguments); + this.add('router:main', _routing.Router.extend({ + location: 'none' + })); + return application; + } + + [`@test Destroying a route after the router does create an undestroyed 'toplevelView'`](assert) { + (0, _internalTestHelpers.runTask)(() => { + this.createApplication(); + this.addTemplate('index', `Index!`); + this.addTemplate('application', `Application! {{outlet}}`); + }); + var router = this.applicationInstance.lookup('router:main'); + var route = this.applicationInstance.lookup('route:index'); + (0, _internalTestHelpers.runTask)(() => router.destroy()); + assert.equal(router._toplevelView, null, 'the toplevelView was cleared'); + (0, _internalTestHelpers.runTask)(() => route.destroy()); + assert.equal(router._toplevelView, null, 'the toplevelView was not reinitialized'); + (0, _internalTestHelpers.runTask)(() => this.application.destroy()); + assert.equal(router._toplevelView, null, 'the toplevelView was not reinitialized'); + } + + [`@test initializers can augment an applications customEvents hash`](assert) { + assert.expect(1); + + var MyApplication = _application.default.extend(); + + MyApplication.initializer({ + name: 'customize-things', + + initialize(application) { + application.customEvents = { + wowza: 'wowza' + }; + } + + }); + (0, _internalTestHelpers.runTask)(() => { + this.createApplication({}, MyApplication); + this.add('component:foo-bar', _glimmer.Component.extend({ + wowza() { + assert.ok(true, 'fired the event!'); + } + + })); + this.addTemplate('application', `{{foo-bar}}`); + this.addTemplate('components/foo-bar', `
`); + }); + this.$('#wowza-thingy').trigger('wowza'); + } + + [`@test instanceInitializers can augment an the customEvents hash`](assert) { + assert.expect(1); + + var MyApplication = _application.default.extend(); + + MyApplication.instanceInitializer({ + name: 'customize-things', + + initialize(application) { + application.customEvents = { + herky: 'jerky' + }; + } + + }); + (0, _internalTestHelpers.runTask)(() => { + this.createApplication({}, MyApplication); + this.add('component:foo-bar', _glimmer.Component.extend({ + jerky() { + assert.ok(true, 'fired the event!'); + } + + })); + this.addTemplate('application', `{{foo-bar}}`); + this.addTemplate('components/foo-bar', `
`); + }); + this.$('#herky-thingy').trigger('herky'); + } + + }); +}); +define("ember/tests/component_context_test", ["@ember/controller", "@ember/-internals/glimmer", "internal-test-helpers"], function (_controller, _glimmer, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Application Lifecycle - Component Context', class extends _internalTestHelpers.ApplicationTestCase { + ['@test Components with a block should have the proper content when a template is provided'](assert) { + this.addTemplate('application', ` +
+ {{#my-component}}{{this.text}}{{/my-component}} +
+ `); + this.add('controller:application', _controller.default.extend({ + text: 'outer' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + text: 'inner' + }), + template: `{{this.text}}-{{yield}}` + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'inner-outer', 'The component is composed correctly'); + }); + } + + ['@test Components with a block should yield the proper content without a template provided'](assert) { + this.addTemplate('application', ` +
+ {{#my-component}}{{this.text}}{{/my-component}} +
+ `); + this.add('controller:application', _controller.default.extend({ + text: 'outer' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + text: 'inner' + }) + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'outer', 'The component is composed correctly'); + }); + } + + ['@test Components without a block should have the proper content when a template is provided'](assert) { + this.addTemplate('application', ` +
{{my-component}}
+ `); + this.add('controller:application', _controller.default.extend({ + text: 'outer' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + text: 'inner' + }), + template: '{{this.text}}' + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'inner', 'The component is composed correctly'); + }); + } + + ['@test Components without a block should have the proper content'](assert) { + this.addTemplate('application', ` +
{{my-component}}
+ `); + this.add('controller:application', _controller.default.extend({ + text: 'outer' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + didInsertElement() { + this.element.innerHTML = 'Some text inserted'; + } + + }) + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'Some text inserted', 'The component is composed correctly'); + }); + } + + ['@test properties of a component without a template should not collide with internal structures [DEPRECATED]'](assert) { + this.addTemplate('application', ` +
{{my-component data=this.foo}}
`); + this.add('controller:application', _controller.default.extend({ + text: 'outer', + foo: 'Some text inserted' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + didInsertElement() { + this.element.innerHTML = this.get('data'); + } + + }) + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'Some text inserted', 'The component is composed correctly'); + }); + } + + ['@test attrs property of a component without a template should not collide with internal structures'](assert) { + this.addTemplate('application', ` +
{{my-component attrs=this.foo}}
+ `); + this.add('controller:application', _controller.default.extend({ + text: 'outer', + foo: 'Some text inserted' + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + didInsertElement() { + this.element.innerHTML = this.get('attrs.attrs.value'); + } + + }) + }); + return this.visit('/').then(() => { + var text = (0, _internalTestHelpers.getTextOf)(this.element.querySelector('#wrapper')); + assert.equal(text, 'Some text inserted', 'The component is composed correctly'); + }); + } + + ['@test Components trigger actions in the parents context when called from within a block'](assert) { + this.addTemplate('application', ` +
+ {{#my-component}} + Fizzbuzz + {{/my-component}} +
+ `); + this.add('controller:application', _controller.default.extend({ + actions: { + fizzbuzz() { + assert.ok(true, 'action triggered on parent'); + } + + } + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({}) + }); + return this.visit('/').then(() => { + this.$('#fizzbuzz', '#wrapper').click(); + }); + } + + ['@test Components trigger actions in the components context when called from within its template'](assert) { + this.addTemplate('application', ` +
{{#my-component}}{{text}}{{/my-component}}
+ `); + this.add('controller:application', _controller.default.extend({ + actions: { + fizzbuzz() { + assert.ok(false, 'action on the wrong context'); + } + + } + })); + this.addComponent('my-component', { + ComponentClass: _glimmer.Component.extend({ + actions: { + fizzbuzz() { + assert.ok(true, 'action triggered on component'); + } + + } + }), + template: `Fizzbuzz` + }); + return this.visit('/').then(() => { + this.$('#fizzbuzz', '#wrapper').click(); + }); + } + + }); +}); +define("ember/tests/component_registration_test", ["@ember/application", "@ember/controller", "@ember/-internals/glimmer", "ember-template-compiler", "internal-test-helpers", "@ember/-internals/environment"], function (_application, _controller, _glimmer, _emberTemplateCompiler, _internalTestHelpers, _environment) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Application Lifecycle - Component Registration', class extends _internalTestHelpers.ApplicationTestCase { + // This is necessary for this.application.instanceInitializer to not leak between tests + createApplication(options) { + return super.createApplication(options, _application.default.extend()); + } + + ['@test The helper becomes the body of the component'](assert) { + if (_environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS) { + assert.expect(0); + return; + } + + this.addTemplate('components/expand-it', '

hello {{yield}}

'); + this.addTemplate('application', 'Hello world {{#expand-it}}world{{/expand-it}}'); + return this.visit('/').then(() => { + this.assertText('Hello world hello world'); + this.assertComponentElement(this.element.firstElementChild, { + tagName: 'div', + content: '

hello world

' + }); + }); + } + + ['@test The helper becomes the body of the component (ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = true;)'](assert) { + if (!_environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS) { + assert.expect(0); + return; + } + + this.addTemplate('components/expand-it', '

hello {{yield}}

'); + this.addTemplate('application', 'Hello world {{#expand-it}}world{{/expand-it}}'); + return this.visit('/').then(() => { + this.assertInnerHTML('Hello world

hello world

'); + _environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = false; + }); + } + + ['@test If a component is registered, it is used'](assert) { + this.addTemplate('components/expand-it', '

hello {{yield}}

'); + this.addTemplate('application', `Hello world {{#expand-it}}world{{/expand-it}}`); + this.application.instanceInitializer({ + name: 'expand-it-component', + + initialize(applicationInstance) { + applicationInstance.register('component:expand-it', _glimmer.Component.extend({ + classNames: 'testing123' + })); + } + + }); + return this.visit('/').then(() => { + var text = this.$('div.testing123').text().trim(); + assert.equal(text, 'hello world', 'The component is composed correctly'); + }); + } + + ['@test Late-registered components can be rendered with custom `layout` property'](assert) { + this.addTemplate('application', `
there goes {{my-hero}}
`); + this.application.instanceInitializer({ + name: 'my-hero-component', + + initialize(applicationInstance) { + applicationInstance.register('component:my-hero', _glimmer.Component.extend({ + classNames: 'testing123', + layout: (0, _emberTemplateCompiler.compile)('watch him as he GOES') + })); + } + + }); + return this.visit('/').then(() => { + var text = this.$('#wrapper').text().trim(); + assert.equal(text, 'there goes watch him as he GOES', 'The component is composed correctly'); + }); + } + + ['@test Late-registered components can be rendered with template registered on the container'](assert) { + this.addTemplate('application', `
hello world {{sally-rutherford}}-{{#sally-rutherford}}!!!{{/sally-rutherford}}
`); + this.application.instanceInitializer({ + name: 'sally-rutherford-component-template', + + initialize(applicationInstance) { + applicationInstance.register('template:components/sally-rutherford', (0, _emberTemplateCompiler.compile)('funkytowny{{yield}}')); + } + + }); + this.application.instanceInitializer({ + name: 'sally-rutherford-component', + + initialize(applicationInstance) { + applicationInstance.register('component:sally-rutherford', _glimmer.Component); + } + + }); + return this.visit('/').then(() => { + var text = this.$('#wrapper').text().trim(); + assert.equal(text, 'hello world funkytowny-funkytowny!!!', 'The component is composed correctly'); + }); + } + + ['@test Late-registered components can be rendered with ONLY the template registered on the container'](assert) { + this.addTemplate('application', `
hello world {{borf-snorlax}}-{{#borf-snorlax}}!!!{{/borf-snorlax}}
`); + this.application.instanceInitializer({ + name: 'borf-snorlax-component-template', + + initialize(applicationInstance) { + applicationInstance.register('template:components/borf-snorlax', (0, _emberTemplateCompiler.compile)('goodfreakingTIMES{{yield}}')); + } + + }); + return this.visit('/').then(() => { + var text = this.$('#wrapper').text().trim(); + assert.equal(text, 'hello world goodfreakingTIMES-goodfreakingTIMES!!!', 'The component is composed correctly'); + }); + } + + ['@test Assigning layoutName to a component should setup the template as a layout'](assert) { + assert.expect(1); + this.addTemplate('application', `
{{#my-component}}{{this.text}}{{/my-component}}
`); + this.addTemplate('foo-bar-baz', '{{this.text}}-{{yield}}'); + this.application.instanceInitializer({ + name: 'application-controller', + + initialize(applicationInstance) { + applicationInstance.register('controller:application', _controller.default.extend({ + text: 'outer' + })); + } + + }); + this.application.instanceInitializer({ + name: 'my-component-component', + + initialize(applicationInstance) { + applicationInstance.register('component:my-component', _glimmer.Component.extend({ + text: 'inner', + layoutName: 'foo-bar-baz' + })); + } + + }); + return this.visit('/').then(() => { + var text = this.$('#wrapper').text().trim(); + assert.equal(text, 'inner-outer', 'The component is composed correctly'); + }); + } + + ['@test Assigning layoutName and layout to a component should use the `layout` value'](assert) { + assert.expect(1); + this.addTemplate('application', `
{{#my-component}}{{this.text}}{{/my-component}}
`); + this.addTemplate('foo-bar-baz', 'No way!'); + this.application.instanceInitializer({ + name: 'application-controller-layout', + + initialize(applicationInstance) { + applicationInstance.register('controller:application', _controller.default.extend({ + text: 'outer' + })); + } + + }); + this.application.instanceInitializer({ + name: 'my-component-component-layout', + + initialize(applicationInstance) { + applicationInstance.register('component:my-component', _glimmer.Component.extend({ + text: 'inner', + layoutName: 'foo-bar-baz', + layout: (0, _emberTemplateCompiler.compile)('{{this.text}}-{{yield}}') + })); + } + + }); + return this.visit('/').then(() => { + var text = this.$('#wrapper').text().trim(); + assert.equal(text, 'inner-outer', 'The component is composed correctly'); + }); + } + + async ['@test Using name of component that does not exist'](assert) { + this.addTemplate('application', `
{{#no-good}} {{/no-good}}
`); + + if (true + /* DEBUG */ + ) { + await assert.rejectsAssertion(this.visit('/'), /Attempted to resolve `no-good`/); + } else { + // Rejects with a worse error message in production + await assert.rejects(this.visit('/')); + } + } + + }); +}); +define("ember/tests/controller_test", ["@ember/controller", "internal-test-helpers", "@ember/-internals/glimmer"], function (_controller, _internalTestHelpers, _glimmer) { + "use strict"; + + /* + In Ember 1.x, controllers subtly affect things like template scope + and action targets in exciting and often inscrutable ways. This test + file contains integration tests that verify the correct behavior of + the many parts of the system that change and rely upon controller scope, + from the runtime up to the templating layer. + */ + (0, _internalTestHelpers.moduleFor)('Template scoping examples', class extends _internalTestHelpers.ApplicationTestCase { + ['@test Actions inside an outlet go to the associated controller'](assert) { + this.add('controller:index', _controller.default.extend({ + actions: { + componentAction() { + assert.ok(true, 'controller received the action'); + } + + } + })); + this.addComponent('component-with-action', { + ComponentClass: _glimmer.Component.extend({ + classNames: ['component-with-action'], + + click() { + this.action(); + } + + }) + }); + this.addTemplate('index', '{{component-with-action action=(action "componentAction")}}'); + return this.visit('/').then(() => { + (0, _internalTestHelpers.runTask)(() => this.$('.component-with-action').click()); + }); + } + + }); +}); +define("ember/tests/ember-test-helpers-test", ["rsvp", "@ember/application", "@ember/runloop", "ember-template-compiler", "internal-test-helpers"], function (_rsvp, _application, _runloop, _emberTemplateCompiler, _internalTestHelpers) { + "use strict"; + + var { + module, + test + } = QUnit; + /* + This test file is intended to emulate what @ember/test-helpers does, and + should be considered a "smoke test" of when a given change will break + existing versions of @ember/test-helpers. + + This generally means that we will have to represent multiple versions of + `@ember/test-helpers` here (will make a nested module for each significant + revision). + */ + + module('@ember/test-helpers emulation test', function () { + module('v1.6.0', function () { + var EMPTY_TEMPLATE = (0, _emberTemplateCompiler.compile)(''); + + function settled() { + return new _rsvp.Promise(function (resolve) { + var watcher = setInterval(() => { + if ((0, _runloop._getCurrentRunLoop)() || (0, _runloop._hasScheduledTimers)()) { + return; + } // Stop polling + + + clearInterval(watcher); // Synchronously resolve the promise + + (0, _runloop.run)(null, resolve); + }, 10); + }); + } + + async function setupContext(context) { + // condensed version of https://github.com/emberjs/ember-test-helpers/blob/v1.6.0/addon-test-support/%40ember/test-helpers/build-owner.ts#L38 + // without support for "custom resolver" + await context.application.boot(); + context.owner = await context.application.buildInstance().boot(); + } + + function setupRenderingContext(context) { + var { + owner + } = context; + var OutletView = owner.factoryFor('view:-outlet'); + var environment = owner.lookup('-environment:main'); + var outletTemplateFactory = owner.lookup('template:-outlet'); + var toplevelView = OutletView.create({ + environment, + template: outletTemplateFactory + }); + owner.register('-top-level-view:main', { + create() { + return toplevelView; + } + + }); // initially render a simple empty template + + return render(EMPTY_TEMPLATE, context).then(() => { + var rootElement = document.querySelector(owner.rootElement); + (0, _runloop.run)(toplevelView, 'appendTo', rootElement); + context.element = rootElement; + return settled(); + }); + } + + var templateId = 0; + + function render(template, context) { + var { + owner + } = context; + var toplevelView = owner.lookup('-top-level-view:main'); + var OutletTemplate = owner.lookup('template:-outlet'); + templateId += 1; + var templateFullName = `template:-undertest-${templateId}`; + owner.register(templateFullName, template); + var outletState = { + render: { + owner, + into: undefined, + outlet: 'main', + name: 'application', + controller: undefined, + ViewClass: undefined, + template: OutletTemplate + }, + outlets: { + main: { + render: { + owner, + into: undefined, + outlet: 'main', + name: 'index', + controller: context, + ViewClass: undefined, + template: owner.lookup(templateFullName), + outlets: {} + }, + outlets: {} + } + } + }; + toplevelView.setOutletState(outletState); + return settled(); + } + + module('setupRenderingContext', function (hooks) { + hooks.beforeEach(async function () { + this.application = _application.default.create({ + rootElement: '#qunit-fixture', + autoboot: false, + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + await setupContext(this); + await setupRenderingContext(this); + }); + hooks.afterEach(function () { + (0, _runloop.run)(this.owner, 'destroy'); + (0, _runloop.run)(this.application, 'destroy'); + }); + test('it basically works', async function (assert) { + await render((0, _emberTemplateCompiler.compile)('Hi!'), this); + assert.equal(this.element.textContent, 'Hi!'); + }); + }); + }); + }); +}); +define("ember/tests/error_handler_test", ["@ember/debug", "@ember/runloop", "@ember/-internals/error-handling", "rsvp", "internal-test-helpers"], function (_debug, _runloop, _errorHandling, _rsvp, _internalTestHelpers) { + "use strict"; + + var HAS_UNHANDLED_REJECTION_HANDLER = ('onunhandledrejection' in window); + var QUNIT_ON_UNHANDLED_REJECTION = QUnit.onUnhandledRejection; + var WINDOW_ONERROR; + + function runThatThrowsSync(message = 'Error for testing error handling') { + return (0, _runloop.run)(() => { + throw new Error(message); + }); + } + + (0, _internalTestHelpers.moduleFor)('error_handler', class extends _internalTestHelpers.AbstractTestCase { + beforeEach() { + // capturing this outside of module scope to ensure we grab + // the test frameworks own window.onerror to reset it + WINDOW_ONERROR = window.onerror; + } + + afterEach() { + (0, _debug.setTesting)(_debug.isTesting); + window.onerror = WINDOW_ONERROR; + (0, _errorHandling.setOnerror)(undefined); + QUnit.onUnhandledRejection = QUNIT_ON_UNHANDLED_REJECTION; + } + + ['@test by default there is no onerror - sync run'](assert) { + assert.strictEqual((0, _errorHandling.getOnerror)(), undefined, 'precond - there should be no Ember.onerror set by default'); + assert.throws(runThatThrowsSync, Error, 'errors thrown sync are catchable'); + } + + ['@test when Ember.onerror (which rethrows) is registered - sync run'](assert) { + assert.expect(2); + (0, _errorHandling.setOnerror)(function (error) { + assert.ok(true, 'onerror called'); + throw error; + }); + assert.throws(runThatThrowsSync, Error, 'error is thrown'); + } + + ['@test when Ember.onerror (which does not rethrow) is registered - sync run'](assert) { + assert.expect(2); + (0, _errorHandling.setOnerror)(function () { + assert.ok(true, 'onerror called'); + }); + runThatThrowsSync(); + assert.ok(true, 'no error was thrown, Ember.onerror can intercept errors'); + } + + ['@test does not swallow exceptions by default (Ember.testing = true, no Ember.onerror) - sync run'](assert) { + (0, _debug.setTesting)(true); + var error = new Error('the error'); + assert.throws(() => { + (0, _runloop.run)(() => { + throw error; + }); + }, error); + } + + ['@test does not swallow exceptions by default (Ember.testing = false, no Ember.onerror) - sync run'](assert) { + (0, _debug.setTesting)(false); + var error = new Error('the error'); + assert.throws(() => { + (0, _runloop.run)(() => { + throw error; + }); + }, error); + } + + ['@test does not swallow exceptions (Ember.testing = false, Ember.onerror which rethrows) - sync run'](assert) { + assert.expect(2); + (0, _debug.setTesting)(false); + (0, _errorHandling.setOnerror)(function (error) { + assert.ok(true, 'Ember.onerror was called'); + throw error; + }); + var error = new Error('the error'); + assert.throws(() => { + (0, _runloop.run)(() => { + throw error; + }); + }, error); + } + + ['@test Ember.onerror can intercept errors (aka swallow) by not rethrowing (Ember.testing = false) - sync run'](assert) { + assert.expect(1); + (0, _debug.setTesting)(false); + (0, _errorHandling.setOnerror)(function () { + assert.ok(true, 'Ember.onerror was called'); + }); + var error = new Error('the error'); + + try { + (0, _runloop.run)(() => { + throw error; + }); + } catch (e) { + assert.notOk(true, 'Ember.onerror that does not rethrow is intentionally swallowing errors, try / catch wrapping does not see error'); + } + } + + ['@test does not swallow exceptions by default (Ember.testing = true, no Ember.onerror) - async run'](assert) { + var done = assert.async(); + var caughtByWindowOnerror; + (0, _debug.setTesting)(true); + + window.onerror = function (message) { + caughtByWindowOnerror = message; // prevent "bubbling" and therefore failing the test + + return true; + }; + + (0, _runloop.later)(() => { + throw new Error('the error'); + }, 10); + setTimeout(() => { + assert.pushResult({ + result: /the error/.test(caughtByWindowOnerror), + actual: caughtByWindowOnerror, + expected: 'to include `the error`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + done(); + }, 20); + } + + ['@test does not swallow exceptions by default (Ember.testing = false, no Ember.onerror) - async run'](assert) { + var done = assert.async(); + var caughtByWindowOnerror; + (0, _debug.setTesting)(false); + + window.onerror = function (message) { + caughtByWindowOnerror = message; // prevent "bubbling" and therefore failing the test + + return true; + }; + + (0, _runloop.later)(() => { + throw new Error('the error'); + }, 10); + setTimeout(() => { + assert.pushResult({ + result: /the error/.test(caughtByWindowOnerror), + actual: caughtByWindowOnerror, + expected: 'to include `the error`', + message: 'error should bubble out to window.onerror, and therefore fail tests (due to QUnit implementing window.onerror)' + }); + done(); + }, 20); + } + + ['@test Ember.onerror can intercept errors (aka swallow) by not rethrowing (Ember.testing = false) - async run'](assert) { + var done = assert.async(); + (0, _debug.setTesting)(false); + + window.onerror = function () { + assert.notOk(true, 'window.onerror is never invoked when Ember.onerror intentionally swallows errors'); // prevent "bubbling" and therefore failing the test + + return true; + }; + + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called with the error'); + }); + (0, _runloop.later)(() => { + throw thrown; + }, 10); + setTimeout(done, 20); + } + + [`@test errors in promise constructor when Ember.onerror which does not rethrow is present - rsvp`](assert) { + assert.expect(1); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + new _rsvp.default.Promise(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise constructor when Ember.onerror which does rethrow is present - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + new _rsvp.default.Promise(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise constructor when Ember.onerror which does not rethrow is present (Ember.testing = false) - rsvp`](assert) { + assert.expect(1); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + new _rsvp.default.Promise(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise constructor when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + new _rsvp.default.Promise(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise .then callback when Ember.onerror which does not rethrow is present - rsvp`](assert) { + assert.expect(1); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + + _rsvp.default.resolve().then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise .then callback when Ember.onerror which does rethrow is present - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + _rsvp.default.resolve().then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise .then callback when Ember.onerror which does not rethrow is present (Ember.testing = false) - rsvp`](assert) { + assert.expect(1); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + + _rsvp.default.resolve().then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in promise .then callback when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + _rsvp.default.resolve().then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)); + } + + [`@test errors in async promise .then callback when Ember.onerror which does not rethrow is present - rsvp`](assert) { + assert.expect(1); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)).then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 20)); + } + + [`@test errors in async promise .then callback when Ember.onerror which does rethrow is present - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)).then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 20)); + } + + [`@test errors in async promise .then callback when Ember.onerror which does not rethrow is present (Ember.testing = false) - rsvp`](assert) { + assert.expect(1); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + }); + new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)).then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 20)); + } + + [`@test errors in async promise .then callback when Ember.onerror which does rethrow is present (Ember.testing = false) - rsvp`](assert) { + if (!HAS_UNHANDLED_REJECTION_HANDLER) { + assert.expect(0); + return; + } + + assert.expect(2); + (0, _debug.setTesting)(false); + var thrown = new Error('the error'); + (0, _errorHandling.setOnerror)(function (error) { + assert.strictEqual(error, thrown, 'Ember.onerror is called for errors thrown in RSVP promises'); + throw error; + }); // prevent QUnit handler from failing test + + QUnit.onUnhandledRejection = () => {}; + + window.onunhandledrejection = function (event) { + assert.pushResult({ + result: /the error/.test(event.reason), + actual: event.reason, + expected: 'to include `the error`', + message: 'error should bubble out to window.onunhandledrejection, and therefore fail tests (due to QUnit implementing window.onunhandledrejection)' + }); + }; + + new _rsvp.default.Promise(resolve => setTimeout(resolve, 10)).then(() => { + throw thrown; + }); // RSVP.Promise's are configured to settle within the run loop, this + // ensures that run loop has completed + + return new _rsvp.default.Promise(resolve => setTimeout(resolve, 20)); + } + + }); +}); +define("ember/tests/homepage_example_test", ["@ember/-internals/routing", "@ember/-internals/metal", "@ember/-internals/runtime", "internal-test-helpers"], function (_routing, _metal, _runtime, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('The example renders correctly', class extends _internalTestHelpers.ApplicationTestCase { + async ['@test Render index template into application outlet'](assert) { + this.addTemplate('application', '{{outlet}}'); + this.addTemplate('index', '

People

    {{#each @model as |person|}}
  • Hello, {{person.fullName}}!
  • {{/each}}
'); + + var Person = _runtime.Object.extend({ + firstName: null, + lastName: null, + fullName: (0, _metal.computed)('firstName', 'lastName', function () { + return `${this.get('firstName')} ${this.get('lastName')}`; + }) + }); + + this.add('route:index', _routing.Route.extend({ + model() { + return (0, _runtime.A)([Person.create({ + firstName: 'Tom', + lastName: 'Dale' + }), Person.create({ + firstName: 'Yehuda', + lastName: 'Katz' + })]); + } + + })); + await this.visit('/'); + var $ = this.$(); + assert.equal($.findAll('h1').text(), 'People'); + assert.equal($.findAll('li').length, 2); + assert.equal($.findAll('li:nth-of-type(1)').text(), 'Hello, Tom Dale!'); + assert.equal($.findAll('li:nth-of-type(2)').text(), 'Hello, Yehuda Katz!'); + } + + }); +}); +define("ember/tests/integration/multiple-app-test", ["internal-test-helpers", "@ember/application", "@ember/-internals/glimmer", "@ember/-internals/owner", "rsvp"], function (_internalTestHelpers, _application, _glimmer, _owner, _rsvp) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('View Integration', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + document.getElementById('qunit-fixture').innerHTML = ` +
+
+ `; + super(); + (0, _internalTestHelpers.runTask)(() => { + this.createSecondApplication(); + }); + } + + get applicationOptions() { + return Object.assign(super.applicationOptions, { + rootElement: '#one', + router: null + }); + } + + createSecondApplication(options) { + var { + applicationOptions + } = this; + var secondApplicationOptions = { + rootElement: '#two' + }; + var myOptions = Object.assign(applicationOptions, secondApplicationOptions, options); + this.secondApp = _application.default.create(myOptions); + this.secondResolver = this.secondApp.__registry__.resolver; + return this.secondApp; + } + + teardown() { + super.teardown(); + + if (this.secondApp) { + (0, _internalTestHelpers.runTask)(() => { + this.secondApp.destroy(); + }); + } + } + + addFactoriesToResolver(actions, resolver) { + resolver.add('component:special-button', _glimmer.Component.extend({ + actions: { + doStuff() { + var rootElement = (0, _owner.getOwner)(this).application.rootElement; + actions.push(rootElement); + } + + } + })); + resolver.add('template:index', this.compile(` +

Node 1

{{special-button}} + `, { + moduleName: 'my-app/templates/index.hbs' + })); + resolver.add('template:components/special-button', this.compile(` + + `, { + moduleName: 'my-app/templates/components/special-button.hbs' + })); + } + + [`@test booting multiple applications can properly handle events`](assert) { + var actions = []; + this.addFactoriesToResolver(actions, this.resolver); + this.addFactoriesToResolver(actions, this.secondResolver); + return (0, _rsvp.resolve)().then(() => this.application.visit('/')).then(() => this.secondApp.visit('/')).then(() => { + document.querySelector('#two .do-stuff').click(); + document.querySelector('#one .do-stuff').click(); + assert.deepEqual(actions, ['#two', '#one']); + }); + } + + }); +}); +define("ember/tests/production_build_test", ["@ember/debug", "internal-test-helpers"], function (_debug, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('production builds', class extends _internalTestHelpers.AbstractTestCase { + ['@test assert does not throw in production builds'](assert) { + if (!true + /* DEBUG */ + ) { + assert.expect(1); + + try { + (true && !(false) && (0, _debug.assert)('Should not throw')); + assert.ok(true, 'Ember.assert did not throw'); + } catch (e) { + assert.ok(false, `Expected assert not to throw but it did: ${e.message}`); + } + } else { + assert.expect(0); + } + } + + ['@test runInDebug does not run the callback in production builds'](assert) { + if (!true + /* DEBUG */ + ) { + var fired = false; + (0, _debug.runInDebug)(() => fired = true); + assert.equal(fired, false, 'runInDebug callback should not be ran'); + } else { + assert.expect(0); + } + } + + }); +}); +define("ember/tests/reexports_test", ["ember/index", "require", "@ember/canary-features", "internal-test-helpers"], function (_index, _require, _canaryFeatures, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('ember reexports', class extends _internalTestHelpers.AbstractTestCase { + [`@test Ember exports correctly`](assert) { + allExports.forEach(reexport => { + var [path, moduleId, exportName] = reexport; // default path === exportName if none present + + if (!exportName) { + exportName = path; + } + + (0, _internalTestHelpers.confirmExport)(_index.default, assert, path, moduleId, exportName); + }); + } + + ['@skip Ember.String.htmlSafe exports correctly (but deprecated)'](assert) { + var glimmer = (0, _require.default)("@ember/-internals/glimmer"); + expectDeprecation(() => { + assert.equal(_index.default.String.htmlSafe, glimmer.htmlSafe, 'Ember.String.htmlSafe is exported correctly'); + }, /Importing htmlSafe from '@ember\/string' is deprecated/); + assert.notEqual(glimmer.htmlSafe, undefined, 'Ember.String.htmlSafe is not `undefined`'); + } + + ['@skip Ember.String.isHTMLSafe exports correctly (but deprecated)'](assert) { + var glimmer = (0, _require.default)("@ember/-internals/glimmer"); + expectDeprecation(() => { + assert.equal(_index.default.String.isHTMLSafe, glimmer.isHTMLSafe, 'Ember.String.isHTMLSafe is exported correctly'); + }, /Importing isHTMLSafe from '@ember\/string' is deprecated/); + assert.notEqual(glimmer.isHTMLSafe, undefined, 'Ember.String.isHTMLSafe is not `undefined`'); + } + + '@test Ember.FEATURES is exported'(assert) { + for (var feature in _canaryFeatures.FEATURES) { + assert.equal(_index.default.FEATURES[feature], _canaryFeatures.FEATURES[feature], 'Ember.FEATURES contains ${feature} with correct value'); + } + } + + }); + var allExports = [// @ember/application + ['Application', '@ember/application', 'default'], ['getOwner', '@ember/application', 'getOwner'], ['onLoad', '@ember/application', 'onLoad'], ['runLoadHooks', '@ember/application', 'runLoadHooks'], ['setOwner', '@ember/application', 'setOwner'], // @ember/application/instance + ['ApplicationInstance', '@ember/application/instance', 'default'], // @ember/application/namespace + ['Namespace', '@ember/application/namespace', 'default'], // @ember/array + ['Array', '@ember/array', 'default'], ['A', '@ember/array', 'A'], ['isArray', '@ember/array', 'isArray'], ['makeArray', '@ember/array', 'makeArray'], // @ember/array/mutable + ['MutableArray', '@ember/array/mutable', 'default'], // @ember/array/proxy + ['ArrayProxy', '@ember/array/proxy', 'default'], // @ember/canary-features + ['FEATURES.isEnabled', '@ember/canary-features', 'isEnabled'], // @ember/component + ['Component', '@ember/component', 'default'], ['_componentManagerCapabilities', '@ember/component', 'capabilities'], ['_getComponentTemplate', '@ember/component', 'getComponentTemplate'], ['_setComponentManager', '@ember/component', 'setComponentManager'], ['_setComponentTemplate', '@ember/component', 'setComponentTemplate'], // @ember/component/helper + ['Helper', '@ember/component/helper', 'default'], ['Helper.helper', '@ember/component/helper', 'helper'], // @ember/component/template-only + ['_templateOnlyComponent', '@ember/component/template-only', 'default'], // @ember/controller + ['Controller', '@ember/controller', 'default'], ['inject.controller', '@ember/controller', 'inject'], // @ember/debug + ['deprecateFunc', '@ember/debug', 'deprecateFunc'], ['deprecate', '@ember/debug', 'deprecate'], ['assert', '@ember/debug', 'assert'], ['debug', '@ember/debug', 'debug'], ['inspect', '@ember/debug', 'inspect'], ['Debug.registerDeprecationHandler', '@ember/debug', 'registerDeprecationHandler'], ['Debug.registerWarnHandler', '@ember/debug', 'registerWarnHandler'], ['runInDebug', '@ember/debug', 'runInDebug'], ['warn', '@ember/debug', 'warn'], ['testing', '@ember/debug', { + get: 'isTesting', + set: 'setTesting' + }], ['_captureRenderTree', '@ember/debug', 'captureRenderTree'], // @ember/debug/container-debug-adapter + ['ContainerDebugAdapter', '@ember/debug/container-debug-adapter', 'default'], // @ember/debug/data-adapter + ['DataAdapter', '@ember/debug/data-adapter', 'default'], // @ember/destroyable + true + /* DEBUG */ + ? ['_assertDestroyablesDestroyed', '@ember/destroyable', 'assertDestroyablesDestroyed'] : null, ['_associateDestroyableChild', '@ember/destroyable', 'associateDestroyableChild'], ['destroy', '@ember/destroyable', 'destroy'], true + /* DEBUG */ + ? ['_enableDestroyableTracking', '@ember/destroyable', 'enableDestroyableTracking'] : null, ['_isDestroyed', '@ember/destroyable', 'isDestroyed'], ['_isDestroying', '@ember/destroyable', 'isDestroying'], ['_registerDestructor', '@ember/destroyable', 'registerDestructor'], ['_unregisterDestructor', '@ember/destroyable', 'unregisterDestructor'], // @ember/engine + ['Engine', '@ember/engine', 'default'], // @ember/engine/instance + ['EngineInstance', '@ember/engine/instance', 'default'], // @ember/enumerable + ['Enumerable', '@ember/enumerable', 'default'], // @ember/error + ['Error', '@ember/error', 'default'], // @ember/instrumentation + ['instrument', '@ember/instrumentation', 'instrument'], ['subscribe', '@ember/instrumentation', 'subscribe'], ['Instrumentation.instrument', '@ember/instrumentation', 'instrument'], ['Instrumentation.reset', '@ember/instrumentation', 'reset'], ['Instrumentation.subscribe', '@ember/instrumentation', 'subscribe'], ['Instrumentation.unsubscribe', '@ember/instrumentation', 'unsubscribe'], // @ember/modifier + ['_modifierManagerCapabilities', '@ember/modifier', 'capabilities'], ['_setModifierManager', '@ember/modifier', 'setModifierManager'], ['_on', '@ember/modifier', 'on'], // @ember/helper + ['_helperManagerCapabilities', '@ember/helper', 'capabilities'], ['_setHelperManager', '@ember/helper', 'setHelperManager'], ['_invokeHelper', '@ember/helper', 'invokeHelper'], ['_fn', '@ember/helper', 'fn'], ['_array', '@ember/helper', 'array'], ['_hash', '@ember/helper', 'hash'], ['_get', '@ember/helper', 'get'], ['_concat', '@ember/helper', 'concat'], // @ember/object + ['Object', '@ember/object', 'default'], ['_action', '@ember/object', 'action'], ['computed', '@ember/object', 'computed'], ['defineProperty', '@ember/object', 'defineProperty'], ['get', '@ember/object', 'get'], ['getProperties', '@ember/object', 'getProperties'], ['notifyPropertyChange', '@ember/object', 'notifyPropertyChange'], ['observer', '@ember/object', 'observer'], ['set', '@ember/object', 'set'], ['setProperties', '@ember/object', 'setProperties'], ['trySet', '@ember/object', 'trySet'], // @ember/object/compat + ['_dependentKeyCompat', '@ember/object/compat', 'dependentKeyCompat'], // @ember/object/computed + ['ComputedProperty', '@ember/object/computed', 'default'], ['expandProperties', '@ember/object/computed', 'expandProperties'], // @ember/object/core + ['CoreObject', '@ember/object/core', 'default'], // @ember/object/evented + ['Evented', '@ember/object/evented', 'default'], ['on', '@ember/object/evented', 'on'], // @ember/object/events + ['addListener', '@ember/object/events', 'addListener'], ['removeListener', '@ember/object/events', 'removeListener'], ['sendEvent', '@ember/object/events', 'sendEvent'], // @ember/object/internals + ['cacheFor', '@ember/object/internals', 'cacheFor'], ['guidFor', '@ember/object/internals', 'guidFor'], // @ember/object/mixin + ['Mixin', '@ember/object/mixin', 'default'], // @ember/object/observable + ['Observable', '@ember/object/observable', 'default'], // @ember/object/observers + ['addObserver', '@ember/object/observers', 'addObserver'], ['removeObserver', '@ember/object/observers', 'removeObserver'], // @ember/object/promise-proxy-mixin + ['PromiseProxyMixin', '@ember/object/promise-proxy-mixin', 'default'], // @ember/object/proxy + ['ObjectProxy', '@ember/object/proxy', 'default'], // @ember/polyfills + ['assign', '@ember/polyfills', 'assign'], ['platform.hasPropertyAccessors', '@ember/polyfills', 'hasPropertyAccessors'], // @ember/routing/auto-location + ['AutoLocation', '@ember/routing/auto-location', 'default'], // @ember/routing/hash-location + ['HashLocation', '@ember/routing/hash-location', 'default'], // @ember/routing/history-location + ['HistoryLocation', '@ember/routing/history-location', 'default'], // @ember/routing/location + ['Location', '@ember/routing/location', 'default'], // @ember/routing/none-location + ['NoneLocation', '@ember/routing/none-location', 'default'], // @ember/routing/route + ['Route', '@ember/routing/route', 'default'], // @ember/routing/router + ['Router', '@ember/routing/router', 'default'], // @ember/runloop + ['run', '@ember/runloop', 'run'], // @ember/service + ['Service', '@ember/service', 'default'], ['inject.service', '@ember/service', 'service'], // @ember/string + ['String.camelize', '@ember/string', 'camelize'], ['String.capitalize', '@ember/string', 'capitalize'], ['String.classify', '@ember/string', 'classify'], ['String.dasherize', '@ember/string', 'dasherize'], ['String.decamelize', '@ember/string', 'decamelize'], ['String.htmlSafe', '@ember/-internals/glimmer', 'htmlSafe'], ['String.isHTMLSafe', '@ember/-internals/glimmer', 'isHTMLSafe'], ['String.underscore', '@ember/string', 'underscore'], ['String.w', '@ember/string', 'w'], ['STRINGS', '@ember/string', { + get: '_getStrings', + set: '_setStrings' + }], // @ember/template + ['String.htmlSafe', '@ember/template', 'htmlSafe'], ['String.isHTMLSafe', '@ember/template', 'isHTMLSafe'], // @ember/template-compilation + ['HTMLBars.compile', '@ember/template-compilation', 'compileTemplate'], // @ember/template-factory + ['Handlebars.template', '@ember/template-factory', 'createTemplateFactory'], ['HTMLBars.template', '@ember/template-factory', 'createTemplateFactory'], // @ember/test + ['Test.registerAsyncHelper', '@ember/test', 'registerAsyncHelper'], ['Test.registerHelper', '@ember/test', 'registerHelper'], ['Test.registerWaiter', '@ember/test', 'registerWaiter'], ['Test.unregisterHelper', '@ember/test', 'unregisterHelper'], ['Test.unregisterWaiter', '@ember/test', 'unregisterWaiter'], // @ember/test/adapter + ['Test.Adapter', '@ember/test/adapter', 'default'], // @ember/utils + ['compare', '@ember/utils', 'compare'], ['isBlank', '@ember/utils', 'isBlank'], ['isEmpty', '@ember/utils', 'isEmpty'], ['isEqual', '@ember/utils', 'isEqual'], ['isNone', '@ember/utils', 'isNone'], ['isPresent', '@ember/utils', 'isPresent'], ['typeOf', '@ember/utils', 'typeOf'], // @ember/version + ['VERSION', '@ember/version', 'VERSION'], // @glimmer/tracking + ['_tracked', '@glimmer/tracking', 'tracked'], // @glimmer/tracking/primitives/cache + ['_createCache', '@glimmer/tracking/primitives/cache', 'createCache'], ['_cacheGetValue', '@glimmer/tracking/primitives/cache', 'getValue'], ['_cacheIsConst', '@glimmer/tracking/primitives/cache', 'isConst'], // @ember/-internals/environment + ['ENV', '@ember/-internals/environment', { + get: 'getENV' + }], ['lookup', '@ember/-internals/environment', { + get: 'getLookup', + set: 'setLookup' + }], // @ember/-internals/utils + ['GUID_KEY', '@ember/-internals/utils'], ['uuid', '@ember/-internals/utils'], ['generateGuid', '@ember/-internals/utils'], ['canInvoke', '@ember/-internals/utils'], ['wrap', '@ember/-internals/utils'], ['_Cache', '@ember/-internals/utils', 'Cache'], // @ember/-internals/container + ['Registry', '@ember/-internals/container', 'Registry'], ['Container', '@ember/-internals/container', 'Container'], // @ember/-internals/metal + ['_descriptor', '@ember/-internals/metal', 'nativeDescDecorator'], ['_setClassicDecorator', '@ember/-internals/metal', 'setClassicDecorator'], ['_getPath', '@ember/-internals/metal'], ['hasListeners', '@ember/-internals/metal'], ['beginPropertyChanges', '@ember/-internals/metal'], ['endPropertyChanges', '@ember/-internals/metal'], ['changeProperties', '@ember/-internals/metal'], ['libraries', '@ember/-internals/metal'], ['BOOTED', '@ember/-internals/metal', { + get: 'isNamespaceSearchDisabled', + set: 'setNamespaceSearchDisabled' + }], // @ember/-internals/error-handling + ['onerror', '@ember/-internals/error-handling', { + get: 'getOnerror', + set: 'setOnerror' + }], // @ember/-internals/meta + ['meta', '@ember/-internals/meta'], // @ember/-internals/views + ['ViewUtils.isSimpleClick', '@ember/-internals/views', 'isSimpleClick'], ['ViewUtils.getElementView', '@ember/-internals/views', 'getElementView'], ['ViewUtils.getViewElement', '@ember/-internals/views', 'getViewElement'], ['ViewUtils.getViewBounds', '@ember/-internals/views', 'getViewBounds'], ['ViewUtils.getViewClientRects', '@ember/-internals/views', 'getViewClientRects'], ['ViewUtils.getViewBoundingClientRect', '@ember/-internals/views', 'getViewBoundingClientRect'], ['ViewUtils.getRootViews', '@ember/-internals/views', 'getRootViews'], ['ViewUtils.getChildViews', '@ember/-internals/views', 'getChildViews'], ['ViewUtils.isSerializationFirstNode', '@ember/-internals/glimmer', 'isSerializationFirstNode'], ['ComponentLookup', '@ember/-internals/views'], ['EventDispatcher', '@ember/-internals/views'], // @ember/-internals/glimmer + ['TEMPLATES', '@ember/-internals/glimmer', { + get: 'getTemplates', + set: 'setTemplates' + }], ['Handlebars.Utils.escapeExpression', '@ember/-internals/glimmer', 'escapeExpression'], ['_Input', '@ember/-internals/glimmer', 'Input'], // @ember/-internals/runtime + ['_RegistryProxyMixin', '@ember/-internals/runtime', 'RegistryProxyMixin'], ['_ContainerProxyMixin', '@ember/-internals/runtime', 'ContainerProxyMixin'], ['Comparable', '@ember/-internals/runtime'], ['ActionHandler', '@ember/-internals/runtime'], ['NativeArray', '@ember/-internals/runtime'], ['MutableEnumerable', '@ember/-internals/runtime'], ['ControllerMixin', '@ember/controller/lib/controller_mixin', 'default'], ['_ProxyMixin', '@ember/-internals/runtime'], // @ember/-internals/routing + ['controllerFor', '@ember/-internals/routing'], ['generateControllerFactory', '@ember/-internals/routing'], ['generateController', '@ember/-internals/routing'], ['RouterDSL', '@ember/-internals/routing'], // backburner + ['_Backburner', 'backburner', 'default'], // rsvp + [null, 'rsvp', 'default'], [null, 'rsvp', 'Promise'], [null, 'rsvp', 'all'], [null, 'rsvp', 'allSettled'], [null, 'rsvp', 'defer'], [null, 'rsvp', 'denodeify'], [null, 'rsvp', 'filter'], [null, 'rsvp', 'hash'], [null, 'rsvp', 'hashSettled'], [null, 'rsvp', 'map'], [null, 'rsvp', 'off'], [null, 'rsvp', 'on'], [null, 'rsvp', 'race'], [null, 'rsvp', 'reject'], [null, 'rsvp', 'resolve'], // misc. + ['platform.defineProperty', null, { + value: true + }]].filter(Boolean); +}); +define("ember/tests/routing/decoupled_basic_test", ["@ember/-internals/owner", "rsvp", "ember-template-compiler", "@ember/-internals/routing", "@ember/controller", "@ember/-internals/runtime", "internal-test-helpers", "@ember/runloop", "@ember/-internals/metal", "@ember/engine", "router_js"], function (_owner, _rsvp, _emberTemplateCompiler, _routing, _controller, _runtime, _internalTestHelpers, _runloop, _metal, _engine, _router_js) { + "use strict"; + + /* eslint-disable no-console */ + var originalConsoleError; + + function handleURLRejectsWith(context, assert, path, expectedReason) { + return context.visit(path).then(() => { + assert.ok(false, 'expected handleURLing: `' + path + '` to fail'); + }).catch(reason => { + assert.equal(reason.message, expectedReason); + }); + } + + (0, _internalTestHelpers.moduleFor)('Basic Routing - Decoupled from global resolver', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + this.addTemplate('home', '

Hours

'); + this.addTemplate('camelot', '

Is a silly place

'); + this.addTemplate('homepage', '

Megatroll

{{this.name}}

'); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + originalConsoleError = console.error; + } + + teardown() { + super.teardown(); + console.error = originalConsoleError; + } + + handleURLAborts(assert, path) { + (0, _runloop.run)(() => { + var router = this.applicationInstance.lookup('router:main'); + router.handleURL(path).then(function () { + assert.ok(false, 'url: `' + path + '` was NOT to be handled'); + }, function (reason) { + assert.ok(reason && reason.message === 'TransitionAborted', 'url: `' + path + '` was to be aborted'); + }); + }); + } + + async ['@test warn on URLs not included in the route set'](assert) { + await this.visit('/'); + await assert.rejects(this.visit('/what-is-this-i-dont-even'), /\/what-is-this-i-dont-even/); + } + + ['@test The Homepage'](assert) { + return this.visit('/').then(() => { + assert.equal(this.appRouter.currentPath, 'home', 'currently on the home route'); + var text = this.$('.hours').text(); + assert.equal(text, 'Hours', 'the home template was rendered'); + }); + } + + [`@test The Homepage and the Camelot page with multiple Router.map calls`](assert) { + this.router.map(function () { + this.route('camelot', { + path: '/camelot' + }); + }); + return this.visit('/camelot').then(() => { + assert.equal(this.appRouter.currentPath, 'camelot'); + var text = this.$('#camelot').text(); + assert.equal(text, 'Is a silly place', 'the camelot template was rendered'); + return this.visit('/'); + }).then(() => { + assert.equal(this.appRouter.currentPath, 'home'); + var text = this.$('.hours').text(); + assert.equal(text, 'Hours', 'the home template was rendered'); + }); + } + + ['@test The Special Page returning a promise puts the app into a loading state until the promise is resolved']() { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + var menuItem, resolve; + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + menuItem = MenuItem.create({ + id: id + }); + return new _rsvp.default.Promise(function (res) { + resolve = res; + }); + } + + }); + this.add('model:menu_item', MenuItem); + this.addTemplate('special', '

{{@model.id}}

'); + this.addTemplate('loading', '

LOADING!

'); + var visited = (0, _internalTestHelpers.runTask)(() => this.visit('/specials/1')); + this.assertText('LOADING!', 'The app is in the loading state'); + resolve(menuItem); + return visited.then(() => { + this.assertText('1', 'The app is now in the specials state'); + }); + } + + [`@test The loading state doesn't get entered for promises that resolve on the same run loop`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + return { + id: id + }; + } + + }); + this.add('model:menu_item', MenuItem); + this.add('route:loading', _routing.Route.extend({ + enter() { + assert.ok(false, "LoadingRoute shouldn't have been entered."); + } + + })); + this.addTemplate('special', '

{{@model.id}}

'); + this.addTemplate('loading', '

LOADING!

'); + return this.visit('/specials/1').then(() => { + var text = this.$('p').text(); + assert.equal(text, '1', 'The app is now in the specials state'); + }); + } + + ["@test The Special page returning an error invokes SpecialRoute's error handler"](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + var menuItem, promise, resolve; + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + menuItem = MenuItem.create({ + id: id + }); + promise = new _rsvp.default.Promise(res => resolve = res); + return promise; + } + + }); + this.add('model:menu_item', MenuItem); + this.add('route:special', _routing.Route.extend({ + setup() { + throw new Error('Setup error'); + }, + + actions: { + error(reason) { + assert.equal(reason.message, 'Setup error', 'SpecialRoute#error received the error thrown from setup'); + return true; + } + + } + })); + (0, _internalTestHelpers.runTask)(() => handleURLRejectsWith(this, assert, 'specials/1', 'Setup error')); + resolve(menuItem); + } + + ["@test ApplicationRoute's default error handler can be overridden"](assert) { + assert.expect(2); + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + var menuItem, resolve; + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + menuItem = MenuItem.create({ + id: id + }); + return new _rsvp.default.Promise(res => resolve = res); + } + + }); + this.add('model:menu_item', MenuItem); + this.add('route:application', _routing.Route.extend({ + actions: { + error(reason) { + assert.equal(reason.message, 'Setup error', 'error was correctly passed to custom ApplicationRoute handler'); + return true; + } + + } + })); + this.add('route:special', _routing.Route.extend({ + setup() { + throw new Error('Setup error'); + } + + })); + var promise = (0, _internalTestHelpers.runTask)(() => handleURLRejectsWith(this, assert, '/specials/1', 'Setup error')); + resolve(menuItem); + return promise; + } + + async ['@test Events are triggered on the controller if a matching action name is implemented'](assert) { + var done = assert.async(); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + var model = { + name: 'Tom Dale' + }; + var stateIsNotCalled = true; + this.add('route:home', _routing.Route.extend({ + model() { + return model; + }, + + actions: { + showStuff() { + stateIsNotCalled = false; + } + + } + })); + this.addTemplate('home', '{{this.name}}'); + this.add('controller:home', _controller.default.extend({ + actions: { + showStuff(context) { + assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); + assert.deepEqual(context, { + name: 'Tom Dale' + }, 'an event with context is passed'); + done(); + } + + } + })); + await this.visit('/'); + document.getElementById('qunit-fixture').querySelector('a').click(); + } + + async ['@test Events are triggered on the current state when defined in `actions` object'](assert) { + var done = assert.async(); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + var model = { + name: 'Tom Dale' + }; + + var HomeRoute = _routing.Route.extend({ + model() { + return model; + }, + + actions: { + showStuff(obj) { + assert.ok(this instanceof HomeRoute, 'the handler is an App.HomeRoute'); + assert.deepEqual(Object.assign({}, obj), { + name: 'Tom Dale' + }, 'the context is correct'); + done(); + } + + } + }); + + this.add('route:home', HomeRoute); + this.addTemplate('home', '{{@model.name}}'); + await this.visit('/'); + document.getElementById('qunit-fixture').querySelector('a').click(); + } + + async ['@test Events defined in `actions` object are triggered on the current state when routes are nested'](assert) { + var done = assert.async(); + this.router.map(function () { + this.route('root', { + path: '/' + }, function () { + this.route('index', { + path: '/' + }); + }); + }); + var model = { + name: 'Tom Dale' + }; + + var RootRoute = _routing.Route.extend({ + actions: { + showStuff(obj) { + assert.ok(this instanceof RootRoute, 'the handler is an App.HomeRoute'); + assert.deepEqual(Object.assign({}, obj), { + name: 'Tom Dale' + }, 'the context is correct'); + done(); + } + + } + }); + + this.add('route:root', RootRoute); + this.add('route:root.index', _routing.Route.extend({ + model() { + return model; + } + + })); + this.addTemplate('root.index', '{{@model.name}}'); + await this.visit('/'); + document.getElementById('qunit-fixture').querySelector('a').click(); + } + + ['@test Events can be handled by inherited event handlers'](assert) { + assert.expect(4); + + var SuperRoute = _routing.Route.extend({ + actions: { + foo() { + assert.ok(true, 'foo'); + }, + + bar(msg) { + assert.equal(msg, 'HELLO', 'bar hander in super route'); + } + + } + }); + + var RouteMixin = _metal.Mixin.create({ + actions: { + bar(msg) { + assert.equal(msg, 'HELLO', 'bar handler in mixin'); + + this._super(msg); + } + + } + }); + + this.add('route:home', SuperRoute.extend(RouteMixin, { + actions: { + baz() { + assert.ok(true, 'baz', 'baz hander in route'); + } + + } + })); + this.addTemplate('home', ` + Do foo + Do bar with arg + Do bar + `); + return this.visit('/').then(() => { + var rootElement = document.getElementById('qunit-fixture'); + rootElement.querySelector('.do-foo').click(); + rootElement.querySelector('.do-bar-with-arg').click(); + rootElement.querySelector('.do-baz').click(); + }); + } + + async ['@test Actions are not triggered on the controller if a matching action name is implemented as a method'](assert) { + var done = assert.async(); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + var model = { + name: 'Tom Dale' + }; + var stateIsNotCalled = true; + this.add('route:home', _routing.Route.extend({ + model() { + return model; + }, + + actions: { + showStuff(context) { + assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); + assert.deepEqual(context, { + name: 'Tom Dale' + }, 'an event with context is passed'); + done(); + } + + } + })); + this.addTemplate('home', '{{this.name}}'); + this.add('controller:home', _controller.default.extend({ + showStuff() { + stateIsNotCalled = false; + assert.ok(stateIsNotCalled, 'an event on the state is not triggered'); + } + + })); + await this.visit('/'); + document.getElementById('qunit-fixture').querySelector('a').click(); + } + + async ['@test actions can be triggered with multiple arguments'](assert) { + var done = assert.async(); + this.router.map(function () { + this.route('root', { + path: '/' + }, function () { + this.route('index', { + path: '/' + }); + }); + }); + var model1 = { + name: 'Tilde' + }; + var model2 = { + name: 'Tom Dale' + }; + + var RootRoute = _routing.Route.extend({ + actions: { + showStuff(obj1, obj2) { + assert.ok(this instanceof RootRoute, 'the handler is an App.HomeRoute'); + assert.deepEqual(Object.assign({}, obj1), { + name: 'Tilde' + }, 'the first context is correct'); + assert.deepEqual(Object.assign({}, obj2), { + name: 'Tom Dale' + }, 'the second context is correct'); + done(); + } + + } + }); + + this.add('route:root', RootRoute); + this.add('controller:root.index', _controller.default.extend({ + model1: model1, + model2: model2 + })); + this.addTemplate('root.index', '{{this.model1.name}}'); + await this.visit('/'); + document.getElementById('qunit-fixture').querySelector('a').click(); + } + + ['@test transitioning multiple times in a single run loop only sets the URL once'](assert) { + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('foo'); + this.route('bar'); + }); + return this.visit('/').then(() => { + var urlSetCount = 0; + var router = this.applicationInstance.lookup('router:main'); + + router.get('location').setURL = function (path) { + urlSetCount++; + (0, _metal.set)(this, 'path', path); + }; + + assert.equal(urlSetCount, 0); + (0, _runloop.run)(function () { + router.transitionTo('foo'); + router.transitionTo('bar'); + }); + assert.equal(urlSetCount, 1); + assert.equal(router.get('location').getURL(), '/bar'); + }); + } + + ['@test navigating away triggers a url property change'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('foo', { + path: '/foo' + }); + this.route('bar', { + path: '/bar' + }); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + (0, _metal.addObserver)(router, 'url', function () { + assert.ok(true, 'url change event was fired'); + }); + ['foo', 'bar', '/foo'].forEach(destination => (0, _runloop.run)(router, 'transitionTo', destination)); + }); + } + + ['@test using replaceWith calls location.replaceURL if available'](assert) { + var setCount = 0; + var replaceCount = 0; + this.router.reopen({ + location: _routing.NoneLocation.create({ + setURL(path) { + setCount++; + (0, _metal.set)(this, 'path', path); + }, + + replaceURL(path) { + replaceCount++; + (0, _metal.set)(this, 'path', path); + } + + }) + }); + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('foo'); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + assert.equal(setCount, 1); + assert.equal(replaceCount, 0); + (0, _runloop.run)(() => router.replaceWith('foo')); + assert.equal(setCount, 1, 'should not call setURL'); + assert.equal(replaceCount, 1, 'should call replaceURL once'); + assert.equal(router.get('location').getURL(), '/foo'); + }); + } + + ['@test using replaceWith calls setURL if location.replaceURL is not defined'](assert) { + var setCount = 0; + this.router.reopen({ + location: _routing.NoneLocation.create({ + setURL(path) { + setCount++; + (0, _metal.set)(this, 'path', path); + } + + }) + }); + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('foo'); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + assert.equal(setCount, 1); + (0, _runloop.run)(() => router.replaceWith('foo')); + assert.equal(setCount, 2, 'should call setURL once'); + assert.equal(router.get('location').getURL(), '/foo'); + }); + } + + ['@test A redirection hook is provided'](assert) { + this.router.map(function () { + this.route('choose', { + path: '/' + }); + this.route('home'); + }); + var chooseFollowed = 0; + var destination = 'home'; + this.add('route:choose', _routing.Route.extend({ + redirect() { + if (destination) { + expectDeprecation(() => { + this.transitionTo(destination); + }, /Calling transitionTo on a route is deprecated/); + } + }, + + setupController() { + chooseFollowed++; + } + + })); + return this.visit('/').then(() => { + var rootElement = document.getElementById('qunit-fixture'); + assert.equal(chooseFollowed, 0, "The choose route wasn't entered since a transition occurred"); + assert.equal(rootElement.querySelectorAll('h3.hours').length, 1, 'The home template was rendered'); + assert.equal(this.appRouter.currentPath, 'home'); + }); + } + + ['@test Redirecting from the middle of a route aborts the remainder of the routes'](assert) { + assert.expect(4); + this.router.map(function () { + this.route('home'); + this.route('foo', function () { + this.route('bar', { + resetNamespace: true + }, function () { + this.route('baz'); + }); + }); + }); + this.add('route:bar', _routing.Route.extend({ + redirect() { + expectDeprecation(() => { + this.transitionTo('home'); + }, /Calling transitionTo on a route is deprecated/); + }, + + setupController() { + assert.ok(false, 'Should transition before setupController'); + } + + })); + this.add('route:bar-baz', _routing.Route.extend({ + enter() { + assert.ok(false, 'Should abort transition getting to next route'); + } + + })); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + this.handleURLAborts(assert, '/foo/bar/baz'); + assert.equal(router.currentPath, 'home'); + assert.equal(router.get('location').getURL(), '/home'); + }); + } + + ['@test Redirecting to the current target in the middle of a route does not abort initial routing'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('home'); + this.route('foo', function () { + this.route('bar', { + resetNamespace: true + }, function () { + this.route('baz'); + }); + }); + }); + var successCount = 0; + this.add('route:bar', _routing.Route.extend({ + redirect() { + return expectDeprecation(() => { + return this.transitionTo('bar.baz').then(function () { + successCount++; + }); + }, /Calling transitionTo on a route is deprecated/); + }, + + setupController() { + assert.ok(true, "Should still invoke bar's setupController"); + } + + })); + this.add('route:bar.baz', _routing.Route.extend({ + setupController() { + assert.ok(true, "Should still invoke bar.baz's setupController"); + } + + })); + return this.visit('/foo/bar/baz').then(() => { + assert.ok(true, '/foo/bar/baz has been handled'); + assert.equal(this.appRouter.currentPath, 'foo.bar.baz'); + assert.equal(successCount, 1, 'transitionTo success handler was called once'); + }); + } + + ['@test Redirecting to the current target with a different context aborts the remainder of the routes'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('home'); + this.route('foo', function () { + this.route('bar', { + path: 'bar/:id', + resetNamespace: true + }, function () { + this.route('baz'); + }); + }); + }); + var model = { + id: 2 + }; + var count = 0; + this.add('route:bar', _routing.Route.extend({ + afterModel() { + if (count++ > 10) { + assert.ok(false, 'infinite loop'); + } else { + expectDeprecation(() => { + this.transitionTo('bar.baz', model); + }, /Calling transitionTo on a route is deprecated/); + } + } + + })); + this.add('route:bar.baz', _routing.Route.extend({ + setupController() { + assert.ok(true, 'Should still invoke setupController'); + } + + })); + return this.visit('/').then(() => { + this.handleURLAborts(assert, '/foo/bar/1/baz'); + assert.equal(this.appRouter.currentPath, 'foo.bar.baz'); + assert.equal(this.applicationInstance.lookup('router:main').get('location').getURL(), '/foo/bar/2/baz'); + }); + } + + ['@test Transitioning from a parent event does not prevent currentPath from being set'](assert) { + this.router.map(function () { + this.route('foo', function () { + this.route('bar', { + resetNamespace: true + }, function () { + this.route('baz'); + }); + this.route('qux'); + }); + }); + this.add('route:foo', _routing.Route.extend({ + actions: { + goToQux() { + expectDeprecation(() => { + this.transitionTo('foo.qux'); + }, /Calling transitionTo on a route is deprecated/); + } + + } + })); + return this.visit('/foo/bar/baz').then(() => { + assert.ok(true, '/foo/bar/baz has been handled'); + var router = this.applicationInstance.lookup('router:main'); + assert.equal(router.currentPath, 'foo.bar.baz'); + (0, _runloop.run)(() => router.send('goToQux')); + assert.equal(router.currentPath, 'foo.qux'); + assert.equal(router.get('location').getURL(), '/foo/qux'); + }); + } + + ['@test Router accounts for rootURL on page load when using history location'](assert) { + var rootURL = window.location.pathname + '/app'; + var postsTemplateRendered = false; + var setHistory; + + setHistory = function (obj, path) { + obj.set('history', { + state: { + path: path + } + }); + }; + + var location = _routing.HistoryLocation.create({ + initState() { + var path = rootURL + '/posts'; + setHistory(this, path); + this.set('location', { + pathname: path, + href: 'http://localhost/' + path + }); + }, + + replaceState(path) { + setHistory(this, path); + }, + + pushState(path) { + setHistory(this, path); + } + + }); + + this.router.reopen({ + // location: 'historyTest', + location, + rootURL: rootURL + }); + this.router.map(function () { + this.route('posts', { + path: '/posts' + }); + }); + this.add('route:posts', _routing.Route.extend({ + model() {}, + + setupController() { + postsTemplateRendered = true; + + this._super(...arguments); + } + + })); + return this.visit('/').then(() => { + assert.ok(postsTemplateRendered, 'Posts route successfully stripped from rootURL'); + (0, _internalTestHelpers.runDestroy)(location); + location = null; + }); + } + + ['@test The rootURL is passed properly to the location implementation'](assert) { + assert.expect(1); + var rootURL = '/blahzorz'; + this.add('location:history-test', _routing.HistoryLocation.extend({ + rootURL: 'this is not the URL you are looking for', + history: { + pushState() {} + + }, + + initState() { + assert.equal(this.get('rootURL'), rootURL); + } + + })); + this.router.reopen({ + location: 'history-test', + rootURL: rootURL, + + // if we transition in this test we will receive failures + // if the tests are run from a static file + _doURLTransition() { + return _rsvp.default.resolve(''); + } + + }); + return this.visit('/'); + } + + ['@test Generating a URL should not affect currentModel'](assert) { + this.router.map(function () { + this.route('post', { + path: '/posts/:post_id' + }); + }); + var posts = { + 1: { + id: 1 + }, + 2: { + id: 2 + } + }; + this.add('route:post', _routing.Route.extend({ + model(params) { + return posts[params.post_id]; + } + + })); + return this.visit('/posts/1').then(() => { + assert.ok(true, '/posts/1 has been handled'); + var route = this.applicationInstance.lookup('route:post'); + assert.equal(route.modelFor('post'), posts[1]); + var url = this.applicationInstance.lookup('router:main').generate('post', posts[2]); + assert.equal(url, '/posts/2'); + assert.equal(route.modelFor('post'), posts[1]); + }); + } + + ["@test Nested index route is not overridden by parent's implicit index route"](assert) { + this.router.map(function () { + this.route('posts', function () { + this.route('index', { + path: ':category' + }); + }); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + return router.transitionTo('posts', { + category: 'emberjs' + }); + }).then(() => { + var router = this.applicationInstance.lookup('router:main'); + assert.deepEqual(router.location.path, '/posts/emberjs'); + }); + } + + ['@test Promises encountered on app load put app into loading state until resolved'](assert) { + assert.expect(2); + + var deferred = _rsvp.default.defer(); + + this.router.map(function () { + this.route('index', { + path: '/' + }); + }); + this.add('route:index', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + this.addTemplate('index', '

INDEX

'); + this.addTemplate('loading', '

LOADING

'); + (0, _runloop.run)(() => this.visit('/')); + var rootElement = document.getElementById('qunit-fixture'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('p')), 'LOADING', 'The loading state is displaying.'); + (0, _runloop.run)(deferred.resolve); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('p')), 'INDEX', 'The index route is display.'); + } + + ['@test Aborting/redirecting the transition in `willTransition` prevents LoadingRoute from being entered'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('index'); + this.route('nork'); + this.route('about'); + }); + var redirect = false; + this.add('route:index', _routing.Route.extend({ + actions: { + willTransition(transition) { + assert.ok(true, 'willTransition was called'); + + if (redirect) { + // router.js won't refire `willTransition` for this redirect + expectDeprecation(() => { + this.transitionTo('about'); + }, /Calling transitionTo on a route is deprecated/); + } else { + transition.abort(); + } + } + + } + })); + var deferred = null; + this.add('route:loading', _routing.Route.extend({ + activate() { + assert.ok(deferred, 'LoadingRoute should be entered at this time'); + }, + + deactivate() { + assert.ok(true, 'LoadingRoute was exited'); + } + + })); + this.add('route:nork', _routing.Route.extend({ + activate() { + assert.ok(true, 'NorkRoute was entered'); + } + + })); + this.add('route:about', _routing.Route.extend({ + activate() { + assert.ok(true, 'AboutRoute was entered'); + }, + + model() { + if (deferred) { + return deferred.promise; + } + } + + })); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); // Attempted transitions out of index should abort. + + (0, _runloop.run)(router, 'transitionTo', 'nork'); + (0, _runloop.run)(router, 'handleURL', '/nork'); // Attempted transitions out of index should redirect to about + + redirect = true; + (0, _runloop.run)(router, 'transitionTo', 'nork'); + (0, _runloop.run)(router, 'transitionTo', 'index'); // Redirected transitions out of index to a route with a + // promise model should pause the transition and + // activate LoadingRoute + + deferred = _rsvp.default.defer(); + (0, _runloop.run)(router, 'transitionTo', 'nork'); + (0, _runloop.run)(deferred.resolve); + }); + } + + ['@test `activate` event fires on the route'](assert) { + assert.expect(4); + var eventFired = 0; + this.router.map(function () { + this.route('nork'); + }); + this.add('route:nork', _routing.Route.extend({ + init() { + this._super(...arguments); + + this.on('activate', function (transition) { + assert.equal(++eventFired, 1, 'activate event is fired once'); + assert.ok(transition, 'transition is passed to activate event'); + }); + }, + + activate(transition) { + assert.ok(true, 'activate hook is called'); + assert.ok(transition, 'transition is passed to activate hook'); + } + + })); + return this.visit('/nork'); + } + + ['@test `deactivate` event fires on the route'](assert) { + assert.expect(4); + var eventFired = 0; + this.router.map(function () { + this.route('nork'); + this.route('dork'); + }); + this.add('route:nork', _routing.Route.extend({ + init() { + this._super(...arguments); + + this.on('deactivate', function (transition) { + assert.equal(++eventFired, 1, 'deactivate event is fired once'); + assert.ok(transition, 'transition is passed'); + }); + }, + + deactivate(transition) { + assert.ok(true, 'deactivate hook is called'); + assert.ok(transition, 'transition is passed'); + } + + })); + return this.visit('/nork').then(() => this.visit('/dork')); + } + + ['@test Actions can be handled by inherited action handlers'](assert) { + assert.expect(4); + + var SuperRoute = _routing.Route.extend({ + actions: { + foo() { + assert.ok(true, 'foo'); + }, + + bar(msg) { + assert.equal(msg, 'HELLO'); + } + + } + }); + + var RouteMixin = _metal.Mixin.create({ + actions: { + bar(msg) { + assert.equal(msg, 'HELLO'); + + this._super(msg); + } + + } + }); + + this.add('route:home', SuperRoute.extend(RouteMixin, { + actions: { + baz() { + assert.ok(true, 'baz'); + } + + } + })); + this.addTemplate('home', ` + Do foo + Do bar with arg + Do bar + `); + return this.visit('/').then(() => { + var rootElement = document.getElementById('qunit-fixture'); + rootElement.querySelector('.do-foo').click(); + rootElement.querySelector('.do-bar-with-arg').click(); + rootElement.querySelector('.do-baz').click(); + }); + } + + ['@test transitionTo returns Transition when passed a route name'](assert) { + assert.expect(1); + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('bar'); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + var transition = (0, _runloop.run)(() => router.transitionTo('bar')); + assert.equal(transition instanceof _router_js.InternalTransition, true); + }); + } + + ['@test transitionTo returns Transition when passed a url'](assert) { + assert.expect(1); + this.router.map(function () { + this.route('root', { + path: '/' + }); + this.route('bar', function () { + this.route('baz'); + }); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + var transition = (0, _runloop.run)(() => router.transitionTo('/bar/baz')); + assert.equal(transition instanceof _router_js.InternalTransition, true); + }); + } + + ['@test currentRouteName is a property installed on Router that can be used in transitionTo'](assert) { + assert.expect(24); + this.router.map(function () { + this.route('index', { + path: '/' + }); + this.route('be', function () { + this.route('excellent', { + resetNamespace: true + }, function () { + this.route('to', { + resetNamespace: true + }, function () { + this.route('each', { + resetNamespace: true + }, function () { + this.route('other'); + }); + }); + }); + }); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + + function transitionAndCheck(path, expectedPath, expectedRouteName) { + if (path) { + (0, _runloop.run)(router, 'transitionTo', path); + } + + assert.equal(router.currentPath, expectedPath); + assert.equal(router.currentRouteName, expectedRouteName); + } + + transitionAndCheck(null, 'index', 'index'); + transitionAndCheck('/be', 'be.index', 'be.index'); + transitionAndCheck('/be/excellent', 'be.excellent.index', 'excellent.index'); + transitionAndCheck('/be/excellent/to', 'be.excellent.to.index', 'to.index'); + transitionAndCheck('/be/excellent/to/each', 'be.excellent.to.each.index', 'each.index'); + transitionAndCheck('/be/excellent/to/each/other', 'be.excellent.to.each.other', 'each.other'); + transitionAndCheck('index', 'index', 'index'); + transitionAndCheck('be', 'be.index', 'be.index'); + transitionAndCheck('excellent', 'be.excellent.index', 'excellent.index'); + transitionAndCheck('to.index', 'be.excellent.to.index', 'to.index'); + transitionAndCheck('each', 'be.excellent.to.each.index', 'each.index'); + transitionAndCheck('each.other', 'be.excellent.to.each.other', 'each.other'); + }); + } + + ["@test Redirecting with null model doesn't error out"](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('about', { + path: '/about/:hurhurhur' + }); + }); + this.add('route:about', _routing.Route.extend({ + serialize: function (model) { + if (model === null) { + return { + hurhurhur: 'TreeklesMcGeekles' + }; + } + } + })); + this.add('route:home', _routing.Route.extend({ + beforeModel() { + expectDeprecation(() => { + this.transitionTo('about', null); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + assert.equal(router.get('location.path'), '/about/TreeklesMcGeekles'); + }); + } + + async ['@test rejecting the model hooks promise with a non-error prints the `message` property'](assert) { + assert.expect(5); + var rejectedMessage = 'OMG!! SOOOOOO BAD!!!!'; + var rejectedStack = 'Yeah, buddy: stack gets printed too.'; + this.router.map(function () { + this.route('yippie', { + path: '/' + }); + }); + + console.error = function (initialMessage, errorMessage, errorStack) { + assert.equal(initialMessage, 'Error while processing route: yippie', 'a message with the current route name is printed'); + assert.equal(errorMessage, rejectedMessage, "the rejected reason's message property is logged"); + assert.equal(errorStack, rejectedStack, "the rejected reason's stack property is logged"); + }; + + this.add('route:yippie', _routing.Route.extend({ + model() { + return _rsvp.default.reject({ + message: rejectedMessage, + stack: rejectedStack + }); + } + + })); + await assert.rejects(this.visit('/'), function (err) { + assert.equal(err.message, rejectedMessage); + return true; + }, 'expected an exception'); + } + + async ['@test rejecting the model hooks promise with an error with `errorThrown` property prints `errorThrown.message` property'](assert) { + assert.expect(5); + var rejectedMessage = 'OMG!! SOOOOOO BAD!!!!'; + var rejectedStack = 'Yeah, buddy: stack gets printed too.'; + this.router.map(function () { + this.route('yippie', { + path: '/' + }); + }); + + console.error = function (initialMessage, errorMessage, errorStack) { + assert.equal(initialMessage, 'Error while processing route: yippie', 'a message with the current route name is printed'); + assert.equal(errorMessage, rejectedMessage, "the rejected reason's message property is logged"); + assert.equal(errorStack, rejectedStack, "the rejected reason's stack property is logged"); + }; + + this.add('route:yippie', _routing.Route.extend({ + model() { + return _rsvp.default.reject({ + errorThrown: { + message: rejectedMessage, + stack: rejectedStack + } + }); + } + + })); + await assert.rejects(this.visit('/'), function ({ + errorThrown: err + }) { + assert.equal(err.message, rejectedMessage); + return true; + }, 'expected an exception'); + } + + async ['@test rejecting the model hooks promise with no reason still logs error'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('wowzers', { + path: '/' + }); + }); + + console.error = function (initialMessage) { + assert.equal(initialMessage, 'Error while processing route: wowzers', 'a message with the current route name is printed'); + }; + + this.add('route:wowzers', _routing.Route.extend({ + model() { + return _rsvp.default.reject(); + } + + })); + await assert.rejects(this.visit('/')); + } + + async ['@test rejecting the model hooks promise with a string shows a good error'](assert) { + assert.expect(3); + var rejectedMessage = 'Supercalifragilisticexpialidocious'; + this.router.map(function () { + this.route('yondo', { + path: '/' + }); + }); + + console.error = function (initialMessage, errorMessage) { + assert.equal(initialMessage, 'Error while processing route: yondo', 'a message with the current route name is printed'); + assert.equal(errorMessage, rejectedMessage, "the rejected reason's message property is logged"); + }; + + this.add('route:yondo', _routing.Route.extend({ + model() { + return _rsvp.default.reject(rejectedMessage); + } + + })); + await assert.rejects(this.visit('/'), new RegExp(rejectedMessage), 'expected an exception'); + } + + ["@test willLeave, willChangeContext, willChangeModel actions don't fire unless feature flag enabled"](assert) { + assert.expect(1); + this.router.map(function () { + this.route('about'); + }); + + function shouldNotFire() { + assert.ok(false, "this action shouldn't have been received"); + } + + this.add('route:index', _routing.Route.extend({ + actions: { + willChangeModel: shouldNotFire, + willChangeContext: shouldNotFire, + willLeave: shouldNotFire + } + })); + this.add('route:about', _routing.Route.extend({ + setupController() { + assert.ok(true, 'about route was entered'); + } + + })); + return this.visit('/about'); + } + + async ['@test Errors in transitionTo within redirect hook are logged'](assert) { + assert.expect(5); + var actual = []; + this.router.map(function () { + this.route('yondo', { + path: '/' + }); + this.route('stink-bomb'); + }); + this.add('route:yondo', _routing.Route.extend({ + redirect() { + expectDeprecation(() => { + this.transitionTo('stink-bomb', { + something: 'goes boom' + }); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + + console.error = function () { + // push the arguments onto an array so we can detect if the error gets logged twice + actual.push(arguments); + }; + + await assert.rejects(this.visit('/'), /More context objects were passed/); + assert.equal(actual.length, 1, 'the error is only logged once'); + assert.equal(actual[0][0], 'Error while processing route: yondo', 'source route is printed'); + assert.ok(actual[0][1].match(/More context objects were passed than there are dynamic segments for the route: stink-bomb/), 'the error is printed'); + } + + ['@test Errors in transition show error template if available'](assert) { + this.addTemplate('error', "
Error!
"); + this.router.map(function () { + this.route('yondo', { + path: '/' + }); + this.route('stink-bomb'); + }); + this.add('route:yondo', _routing.Route.extend({ + redirect() { + expectDeprecation(() => { + this.transitionTo('stink-bomb', { + something: 'goes boom' + }); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + + console.error = () => {}; + + return this.visit('/').then(() => { + var rootElement = document.querySelector('#qunit-fixture'); + assert.equal(rootElement.querySelectorAll('#error').length, 1, 'Error template was rendered.'); + }); + } + + ['@test Route#resetController gets fired when changing models and exiting routes'](assert) { + assert.expect(4); + this.router.map(function () { + this.route('a', function () { + this.route('b', { + path: '/b/:id', + resetNamespace: true + }, function () {}); + this.route('c', { + path: '/c/:id', + resetNamespace: true + }, function () {}); + }); + this.route('out'); + }); + var calls = []; + + var SpyRoute = _routing.Route.extend({ + setupController() + /* controller, model, transition */ + { + calls.push(['setup', this.routeName]); + }, + + resetController() + /* controller */ + { + calls.push(['reset', this.routeName]); + } + + }); + + this.add('route:a', SpyRoute.extend()); + this.add('route:b', SpyRoute.extend()); + this.add('route:c', SpyRoute.extend()); + this.add('route:out', SpyRoute.extend()); + var router; + return this.visit('/').then(() => { + router = this.applicationInstance.lookup('router:main'); + assert.deepEqual(calls, []); + return (0, _runloop.run)(router, 'transitionTo', 'b', 'b-1'); + }).then(() => { + assert.deepEqual(calls, [['setup', 'a'], ['setup', 'b']]); + calls.length = 0; + return (0, _runloop.run)(router, 'transitionTo', 'c', 'c-1'); + }).then(() => { + assert.deepEqual(calls, [['reset', 'b'], ['setup', 'c']]); + calls.length = 0; + return (0, _runloop.run)(router, 'transitionTo', 'out'); + }).then(() => { + assert.deepEqual(calls, [['reset', 'c'], ['reset', 'a'], ['setup', 'out']]); + }); + } + + async ['@test Exception during initialization of non-initial route is not swallowed'](assert) { + this.router.map(function () { + this.route('boom'); + }); + this.add('route:boom', _routing.Route.extend({ + init() { + throw new Error('boom!'); + } + + })); + await assert.rejects(this.visit('/boom'), /\bboom\b/); + } + + async ['@test Exception during initialization of initial route is not swallowed'](assert) { + this.router.map(function () { + this.route('boom', { + path: '/' + }); + }); + this.add('route:boom', _routing.Route.extend({ + init() { + throw new Error('boom!'); + } + + })); + await assert.rejects(this.visit('/'), /\bboom\b/); + } + + async ['@test Doesnt swallow exception thrown from willTransition'](assert) { + assert.expect(1); + this.addTemplate('application', '{{outlet}}'); + this.addTemplate('index', 'index'); + this.addTemplate('other', 'other'); + this.router.map(function () { + this.route('index', { + path: '/' + }); + this.route('other', function () {}); + }); + this.add('route:index', _routing.Route.extend({ + actions: { + willTransition() { + throw new Error('boom'); + } + + } + })); + await this.visit('/'); + await assert.rejects(this.visit('/other'), /boom/, 'expected an exception but none was thrown'); + } + + ['@test Route serializers work for Engines'](assert) { + assert.expect(2); // Register engine + + var BlogEngine = _engine.default.extend({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + + this.add('engine:blog', BlogEngine); // Register engine route map + + var postSerialize = function (params) { + assert.ok(true, 'serialize hook runs'); + return { + post_id: params.id + }; + }; + + var BlogMap = function () { + this.route('post', { + path: '/post/:post_id', + serialize: postSerialize + }); + }; + + this.add('route-map:blog', BlogMap); + this.router.map(function () { + this.mount('blog'); + }); + return this.visit('/').then(() => { + var router = this.applicationInstance.lookup('router:main'); + assert.equal(router._routerMicrolib.generate('blog.post', { + id: '13' + }), '/blog/post/13', 'url is generated properly'); + }); + } + + async ['@test Defining a Route#serialize method in an Engine throws an error'](assert) { + assert.expect(1); // Register engine + + var BlogEngine = _engine.default.extend({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + + this.add('engine:blog', BlogEngine); // Register engine route map + + var BlogMap = function () { + this.route('post'); + }; + + this.add('route-map:blog', BlogMap); + this.router.map(function () { + this.mount('blog'); + }); + await this.visit('/'); + var router = this.applicationInstance.lookup('router:main'); + + var PostRoute = _routing.Route.extend({ + serialize() {} + + }); + + this.applicationInstance.lookup('engine:blog').register('route:post', PostRoute); + + try { + // TODO: for some reason this doesn't work with assert.reject + await router.transitionTo('blog.post'); + } catch (e) { + assert.ok(e.message.match(/Defining a custom serialize method on an Engine route is not supported/)); + } + } + + ['@test App.destroy does not leave undestroyed views after clearing engines'](assert) { + assert.expect(4); + var engineInstance; // Register engine + + var BlogEngine = _engine.default.extend({ + Resolver: _internalTestHelpers.ModuleBasedTestResolver + }); + + this.add('engine:blog', BlogEngine); + + var EngineIndexRoute = _routing.Route.extend({ + init() { + this._super(...arguments); + + engineInstance = (0, _owner.getOwner)(this); + } + + }); // Register engine route map + + + var BlogMap = function () { + this.route('post'); + }; + + this.add('route-map:blog', BlogMap); + this.router.map(function () { + this.mount('blog'); + }); + return this.visit('/').then(() => { + var engine = this.applicationInstance.lookup('engine:blog'); + engine.register('route:index', EngineIndexRoute); + engine.register('template:index', (0, _emberTemplateCompiler.compile)('Engine Post!')); + return this.visit('/blog'); + }).then(() => { + assert.ok(true, '/blog has been handled'); + var route = engineInstance.lookup('route:index'); + var router = this.applicationInstance.lookup('router:main'); + (0, _runloop.run)(router, 'destroy'); + assert.equal(router._toplevelView, null, 'the toplevelView was cleared'); + (0, _runloop.run)(route, 'destroy'); + assert.equal(router._toplevelView, null, 'the toplevelView was not reinitialized'); + (0, _runloop.run)(this.applicationInstance, 'destroy'); + assert.equal(router._toplevelView, null, 'the toplevelView was not reinitialized'); + }); + } + + ["@test Generated route should be an instance of App's default route if provided"](assert) { + var generatedRoute; + this.router.map(function () { + this.route('posts'); + }); + + var AppRoute = _routing.Route.extend(); + + this.add('route:basic', AppRoute); + return this.visit('/posts').then(() => { + generatedRoute = this.applicationInstance.lookup('route:posts'); + assert.ok(generatedRoute instanceof AppRoute, 'should extend the correct route'); + }); + } + + }); +}); +define("ember/tests/routing/model_loading_test", ["@ember/-internals/routing", "@ember/controller", "@ember/-internals/runtime", "internal-test-helpers", "@ember/runloop", "@ember/-internals/metal"], function (_routing, _controller, _runtime, _internalTestHelpers, _runloop, _metal) { + "use strict"; + + /* eslint-disable no-console */ + var originalConsoleError; + (0, _internalTestHelpers.moduleFor)('Route - model loading', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + this.addTemplate('home', '

Hours

'); + this.addTemplate('camelot', '

Is a silly place

'); + this.addTemplate('homepage', '

Megatroll

{{this.name}}

'); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + originalConsoleError = console.error; + } + + teardown() { + super.teardown(); + console.error = originalConsoleError; + } + + async ['@test warn on URLs not included in the route set'](assert) { + await this.visit('/'); + await assert.rejects(this.visit('/what-is-this-i-dont-even'), /\/what-is-this-i-dont-even/); + } + + ['@test properties that autotrack the model update when the model changes'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('track', { + path: '/track/:id' + }); + }); + + class HomeRoute extends _routing.Route { + async model({ + id + }) { + return { + value: id + }; + } + + } + + class HomeController extends _controller.default { + get derivedProperty() { + return this.model.value || 'value is unset'; + } + + } + + this.add('route:track', HomeRoute); + this.add('controller:track', HomeController); + this.addTemplate('track', '

{{this.derivedProperty}}

'); + return this.visit('/track/2').then(() => { + assert.equal(document.querySelector('h3').innerText, '2', 'the derived property matches the id'); + }).then(() => { + return this.visit('/track/3').then(() => { + assert.equal(document.querySelector('h3').innerText, '3', 'the derived property matches the id'); + }); + }); + } + + ['@test The Homepage with a `setupController` hook'](assert) { + this.addTemplate('home', `
    {{#each this.hours as |entry|}} +
  • {{entry}}
  • + {{/each}} +
+ `); + this.add('route:home', _routing.Route.extend({ + setupController(controller) { + controller.set('hours', ['Monday through Friday: 9am to 5pm', 'Saturday: Noon to Midnight', 'Sunday: Noon to 6pm']); + } + + })); + return this.visit('/').then(() => { + var text = this.$('ul li:nth-child(3)').text(); + assert.equal(text, 'Sunday: Noon to 6pm', 'The template was rendered with the hours context'); + }); + } + + [`@test The route controller is still set when overriding the setupController hook`](assert) { + this.add('route:home', _routing.Route.extend({ + setupController() {// no-op + // importantly, we are not calling this._super + } + + })); + this.add('controller:home', _controller.default.extend()); + return this.visit('/').then(() => { + var homeRoute = this.applicationInstance.lookup('route:home'); + var homeController = this.applicationInstance.lookup('controller:home'); + assert.equal(homeRoute.controller, homeController, 'route controller is the home controller'); + }); + } + + ['@test the route controller can be specified via controllerName'](assert) { + this.addTemplate('home', '

{{this.myValue}}

'); + this.add('route:home', _routing.Route.extend({ + controllerName: 'myController' + })); + this.add('controller:myController', _controller.default.extend({ + myValue: 'foo' + })); + return this.visit('/').then(() => { + var homeRoute = this.applicationInstance.lookup('route:home'); + var myController = this.applicationInstance.lookup('controller:myController'); + var text = this.$('p').text(); + assert.equal(homeRoute.controller, myController, 'route controller is set by controllerName'); + assert.equal(text, 'foo', 'The homepage template was rendered with data from the custom controller'); + }); + } + + [`@test The route controller specified via controllerName is used in render even when a controller with the routeName is available`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.addTemplate('home', '

home: {{this.myValue}}

'); + this.add('route:home', _routing.Route.extend({ + controllerName: 'myController' + })); + this.add('controller:home', _controller.default.extend({ + myValue: 'home' + })); + this.add('controller:myController', _controller.default.extend({ + myValue: 'myController' + })); + return this.visit('/').then(() => { + var homeRoute = this.applicationInstance.lookup('route:home'); + var myController = this.applicationInstance.lookup('controller:myController'); + var text = this.$('p').text(); + assert.equal(homeRoute.controller, myController, 'route controller is set by controllerName'); + assert.equal(text, 'home: myController', 'The homepage template was rendered with data from the custom controller'); + }); + } + + [`@test The Homepage with a 'setupController' hook modifying other controllers`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.add('route:home', _routing.Route.extend({ + setupController() + /* controller */ + { + this.controllerFor('home').set('hours', ['Monday through Friday: 9am to 5pm', 'Saturday: Noon to Midnight', 'Sunday: Noon to 6pm']); + } + + })); + this.addTemplate('home', '
    {{#each this.hours as |entry|}}
  • {{entry}}
  • {{/each}}
'); + return this.visit('/').then(() => { + var text = this.$('ul li:nth-child(3)').text(); + assert.equal(text, 'Sunday: Noon to 6pm', 'The template was rendered with the hours context'); + }); + } + + [`@test The Homepage with a computed model that does not get overridden`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.add('controller:home', _controller.default.extend({ + model: (0, _metal.computed)(function () { + return ['Monday through Friday: 9am to 5pm', 'Saturday: Noon to Midnight', 'Sunday: Noon to 6pm']; + }) + })); + this.addTemplate('home', '
    {{#each this.model as |passage|}}
  • {{passage}}
  • {{/each}}
'); + return this.visit('/').then(() => { + var text = this.$('ul li:nth-child(3)').text(); + assert.equal(text, 'Sunday: Noon to 6pm', 'The template was rendered with the context intact'); + }); + } + + [`@test The Homepage getting its controller context via model`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.add('route:home', _routing.Route.extend({ + model() { + return ['Monday through Friday: 9am to 5pm', 'Saturday: Noon to Midnight', 'Sunday: Noon to 6pm']; + }, + + setupController(controller, model) { + assert.equal(this.controllerFor('home'), controller); + this.controllerFor('home').set('hours', model); + } + + })); + this.addTemplate('home', '
    {{#each this.hours as |entry|}}
  • {{entry}}
  • {{/each}}
'); + return this.visit('/').then(() => { + var text = this.$('ul li:nth-child(3)').text(); + assert.equal(text, 'Sunday: Noon to 6pm', 'The template was rendered with the hours context'); + }); + } + + [`@test The Specials Page getting its model by deserializing the params hash`](assert) { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + this.add('route:special', _routing.Route.extend({ + model(params) { + return _runtime.Object.create({ + menuItemId: params.menu_item_id + }); + } + + })); + this.addTemplate('special', '

{{@model.menuItemId}}

'); + return this.visit('/specials/1').then(() => { + var text = this.$('p').text(); + assert.equal(text, '1', 'The model was used to render the template'); + }); + } + + ['@test The Specials Page defaults to looking models up via `find`']() { + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + return MenuItem.create({ + id + }); + } + + }); + this.add('model:menu_item', MenuItem); + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + this.addTemplate('special', '{{@model.id}}'); + return this.visit('/specials/1').then(() => { + this.assertText('1', 'The model was used to render the template'); + }); + } + + ['@test Moving from one page to another triggers the correct callbacks'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('special', { + path: '/specials/:menu_item_id' + }); + }); + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + return MenuItem.create({ + id: id + }); + } + + }); + this.add('model:menu_item', MenuItem); + this.addTemplate('home', '

Home

'); + this.addTemplate('special', '

{{@model.id}}

'); + return this.visit('/').then(() => { + this.assertText('Home', 'The app is now in the initial state'); + var promiseContext = MenuItem.create({ + id: 1 + }); + return this.visit('/specials/1', promiseContext); + }).then(() => { + assert.equal(this.currentURL, '/specials/1'); + this.assertText('1', 'The app is now transitioned'); + }); + } + + ['@test Nested callbacks are not exited when moving to siblings'](assert) { + var rootSetup = 0; + var rootModel = 0; + var rootSerialize = 0; + var menuItem; + var rootElement; + + var MenuItem = _runtime.Object.extend(); + + MenuItem.reopenClass({ + find(id) { + menuItem = MenuItem.create({ + id: id + }); + return menuItem; + } + + }); + this.router.map(function () { + this.route('root', { + path: '/' + }, function () { + this.route('special', { + path: '/specials/:menu_item_id', + resetNamespace: true + }); + }); + }); + this.add('route:root', _routing.Route.extend({ + model() { + rootModel++; + return this._super(...arguments); + }, + + setupController() { + rootSetup++; + }, + + serialize() { + rootSerialize++; + return this._super(...arguments); + } + + })); + this.add('route:loading', _routing.Route.extend({})); + this.add('route:home', _routing.Route.extend({})); + this.add('route:special', _routing.Route.extend({ + model({ + menu_item_id + }) { + return MenuItem.find(menu_item_id); + }, + + setupController(controller, model) { + (0, _metal.set)(controller, 'model', model); + } + + })); + this.addTemplate('root.index', '

Home

'); + this.addTemplate('special', '

{{@model.id}}

'); + this.addTemplate('loading', '

LOADING!

'); + return this.visit('/').then(() => { + rootElement = document.getElementById('qunit-fixture'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('h3')), 'Home', 'The app is now in the initial state'); + assert.equal(rootSetup, 1, 'The root setup was triggered'); + assert.equal(rootSerialize, 0, 'The root serialize was not called'); + assert.equal(rootModel, 1, 'The root model was called'); + var router = this.applicationInstance.lookup('router:main'); + var menuItem = MenuItem.create({ + id: 1 + }); + return router.transitionTo('special', menuItem).then(function () { + assert.equal(rootSetup, 1, 'The root setup was not triggered again'); + assert.equal(rootSerialize, 0, 'The root serialize was not called'); // TODO: Should this be changed? + + assert.equal(rootModel, 1, 'The root model was called again'); + assert.deepEqual(router.location.path, '/specials/1'); + assert.equal(router.currentPath, 'root.special'); + }); + }); + } + + ['@test Route inherits model from parent route'](assert) { + assert.expect(9); + this.router.map(function () { + this.route('the-post', { + path: '/posts/:post_id' + }, function () { + this.route('comments'); + this.route('shares', { + path: '/shares/:share_id', + resetNamespace: true + }, function () { + this.route('share'); + }); + }); + }); + var post1 = {}; + var post2 = {}; + var post3 = {}; + var share1 = {}; + var share2 = {}; + var share3 = {}; + var posts = { + 1: post1, + 2: post2, + 3: post3 + }; + var shares = { + 1: share1, + 2: share2, + 3: share3 + }; + this.add('route:the-post', _routing.Route.extend({ + model(params) { + return posts[params.post_id]; + } + + })); + this.add('route:the-post.comments', _routing.Route.extend({ + afterModel(post + /*, transition */ + ) { + var parent_model = this.modelFor('the-post'); + assert.equal(post, parent_model); + } + + })); + this.add('route:shares', _routing.Route.extend({ + model(params) { + return shares[params.share_id]; + } + + })); + this.add('route:shares.share', _routing.Route.extend({ + afterModel(share + /*, transition */ + ) { + var parent_model = this.modelFor('shares'); + assert.equal(share, parent_model); + } + + })); + return this.visit('/posts/1/comments').then(() => { + assert.ok(true, 'url: /posts/1/comments was handled'); + return this.visit('/posts/1/shares/1'); + }).then(() => { + assert.ok(true, 'url: /posts/1/shares/1 was handled'); + return this.visit('/posts/2/comments'); + }).then(() => { + assert.ok(true, 'url: /posts/2/comments was handled'); + return this.visit('/posts/2/shares/2'); + }).then(() => { + assert.ok(true, 'url: /posts/2/shares/2 was handled'); + return this.visit('/posts/3/comments'); + }).then(() => { + assert.ok(true, 'url: /posts/3/shares was handled'); + return this.visit('/posts/3/shares/3'); + }).then(() => { + assert.ok(true, 'url: /posts/3/shares/3 was handled'); + }); + } + + ['@test Routes with { resetNamespace: true } inherits model from parent route'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('the-post', { + path: '/posts/:post_id' + }, function () { + this.route('comments', { + resetNamespace: true + }, function () {}); + }); + }); + var post1 = {}; + var post2 = {}; + var post3 = {}; + var posts = { + 1: post1, + 2: post2, + 3: post3 + }; + this.add('route:the-post', _routing.Route.extend({ + model(params) { + return posts[params.post_id]; + } + + })); + this.add('route:comments', _routing.Route.extend({ + afterModel(post + /*, transition */ + ) { + var parent_model = this.modelFor('the-post'); + assert.equal(post, parent_model); + } + + })); + return this.visit('/posts/1/comments').then(() => { + assert.ok(true, '/posts/1/comments'); + return this.visit('/posts/2/comments'); + }).then(() => { + assert.ok(true, '/posts/2/comments'); + return this.visit('/posts/3/comments'); + }).then(() => { + assert.ok(true, '/posts/3/comments'); + }); + } + + ['@test It is possible to get the model from a parent route'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('the-post', { + path: '/posts/:post_id' + }, function () { + this.route('comments', { + resetNamespace: true + }); + }); + }); + var post1 = {}; + var post2 = {}; + var post3 = {}; + var currentPost; + var posts = { + 1: post1, + 2: post2, + 3: post3 + }; + this.add('route:the-post', _routing.Route.extend({ + model(params) { + return posts[params.post_id]; + } + + })); + this.add('route:comments', _routing.Route.extend({ + model() { + assert.equal(this.modelFor('the-post'), currentPost); + } + + })); + currentPost = post1; + return this.visit('/posts/1/comments').then(() => { + assert.ok(true, '/posts/1/comments has been handled'); + currentPost = post2; + return this.visit('/posts/2/comments'); + }).then(() => { + assert.ok(true, '/posts/2/comments has been handled'); + currentPost = post3; + return this.visit('/posts/3/comments'); + }).then(() => { + assert.ok(true, '/posts/3/comments has been handled'); + }); + } + + ['@test Parent route context change'](assert) { + var editCount = 0; + var editedPostIds = (0, _runtime.A)(); + this.addTemplate('application', '{{outlet}}'); + this.addTemplate('posts', '{{outlet}}'); + this.addTemplate('post', '{{outlet}}'); + this.addTemplate('post/index', 'showing'); + this.addTemplate('post/edit', 'editing'); + this.router.map(function () { + this.route('posts', function () { + this.route('post', { + path: '/:postId', + resetNamespace: true + }, function () { + this.route('edit'); + }); + }); + }); + this.add('route:posts', _routing.Route.extend({ + actions: { + showPost(context) { + expectDeprecation(() => { + this.transitionTo('post', context); + }, /Calling transitionTo on a route is deprecated/); + } + + } + })); + this.add('route:post', _routing.Route.extend({ + model(params) { + return { + id: params.postId + }; + }, + + serialize(model) { + return { + postId: model.id + }; + }, + + actions: { + editPost() { + expectDeprecation(() => { + this.transitionTo('post.edit'); + }, /Calling transitionTo on a route is deprecated/); + } + + } + })); + this.add('route:post.edit', _routing.Route.extend({ + model() { + var postId = this.modelFor('post').id; + editedPostIds.push(postId); + return null; + }, + + setup() { + this._super(...arguments); + + editCount++; + } + + })); + return this.visit('/posts/1').then(() => { + assert.ok(true, '/posts/1 has been handled'); + var router = this.applicationInstance.lookup('router:main'); + (0, _runloop.run)(() => router.send('editPost')); + (0, _runloop.run)(() => router.send('showPost', { + id: '2' + })); + (0, _runloop.run)(() => router.send('editPost')); + assert.equal(editCount, 2, 'set up the edit route twice without failure'); + assert.deepEqual(editedPostIds, ['1', '2'], 'modelFor posts.post returns the right context'); + }); + } + + ['@test ApplicationRoute with model does not proxy the currentPath'](assert) { + // TODO: FIXME: + var model = {}; + this.router.map(function () { + this.route('index', { + path: '/' + }); + }); + this.add('route:application', _routing.Route.extend({ + model() { + return model; + } + + })); + return this.visit('/').then(() => { + var routerService = this.applicationInstance.lookup('service:router'); + assert.equal(routerService.currentRouteName, 'index', 'currentPath is index'); + assert.equal('currentPath' in model, false, 'should have defined currentPath on controller'); + }); + } + + ['@test Route model hook finds the same model as a manual find'](assert) { + var post; + + var Post = _runtime.Object.extend(); + + this.add('model:post', Post); + Post.reopenClass({ + find() { + post = this; + return {}; + } + + }); + this.router.map(function () { + this.route('post', { + path: '/post/:post_id' + }); + }); + return this.visit('/post/1').then(() => { + assert.equal(Post, post); + }); + } + + ['@test Routes can refresh themselves causing their model hooks to be re-run'](assert) { + this.router.map(function () { + this.route('parent', { + path: '/parent/:parent_id' + }, function () { + this.route('child'); + }); + }); + var appcount = 0; + this.add('route:application', _routing.Route.extend({ + model() { + ++appcount; + } + + })); + var parentcount = 0; + this.add('route:parent', _routing.Route.extend({ + model(params) { + assert.equal(params.parent_id, '123'); + ++parentcount; + }, + + actions: { + refreshParent() { + this.refresh(); + } + + } + })); + var childcount = 0; + this.add('route:parent.child', _routing.Route.extend({ + model() { + ++childcount; + } + + })); + var router; + return this.visit('/').then(() => { + router = this.applicationInstance.lookup('router:main'); + assert.equal(appcount, 1); + assert.equal(parentcount, 0); + assert.equal(childcount, 0); + return (0, _runloop.run)(router, 'transitionTo', 'parent.child', '123'); + }).then(() => { + assert.equal(appcount, 1); + assert.equal(parentcount, 1); + assert.equal(childcount, 1); + return (0, _runloop.run)(router, 'send', 'refreshParent'); + }).then(() => { + assert.equal(appcount, 1); + assert.equal(parentcount, 2); + assert.equal(childcount, 2); + }); + } + + }); +}); +define("ember/tests/routing/query_params_test", ["@ember/controller", "@ember/string", "@ember/-internals/runtime", "@ember/runloop", "@ember/-internals/meta", "@ember/-internals/metal", "@ember/-internals/routing", "router_js", "internal-test-helpers"], function (_controller, _string, _runtime, _runloop, _meta, _metal, _routing, _router_js, _internalTestHelpers) { + "use strict"; + + function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); + } + + function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object.keys(descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + + return desc; + } + + function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); + } + + (0, _internalTestHelpers.moduleFor)('Query Params - main', class extends _internalTestHelpers.QueryParamTestCase { + async refreshModelWhileLoadingTest(loadingReturn) { + var assert = this.assert; + assert.expect(9); + var appModelCount = 0; + var promiseResolve; + this.add('route:application', _routing.Route.extend({ + queryParams: { + appomg: { + defaultValue: 'applol' + } + }, + + model() + /* params */ + { + appModelCount++; + } + + })); + this.setSingleQPController('index', 'omg', undefined, { + omg: undefined + }); + var actionName = typeof loadingReturn !== 'undefined' ? 'loading' : 'ignore'; + var indexModelCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + actions: { + [actionName]: function () { + return loadingReturn; + } + }, + + model(params) { + indexModelCount++; + + if (indexModelCount === 2) { + assert.deepEqual(params, { + omg: 'lex' + }); + return new _runtime.RSVP.Promise(function (resolve) { + promiseResolve = resolve; + return; + }); + } else if (indexModelCount === 3) { + assert.deepEqual(params, { + omg: 'hello' + }, "Model hook reruns even if the previous one didn't finish"); + } + } + + })); + await this.visit('/'); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 1); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, 'omg', 'lex'); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 2); + await this.setAndFlush(indexController, 'omg', 'hello'); + assert.equal(appModelCount, 1, 'appModelCount is 1'); + assert.equal(indexModelCount, 3); + (0, _runloop.run)(function () { + promiseResolve(); + }); + assert.equal((0, _metal.get)(indexController, 'omg'), 'hello', 'At the end last value prevails'); + } + + ["@test No replaceURL occurs on startup because default values don't show up in URL"](assert) { + assert.expect(1); + this.setSingleQPController('index'); + return this.visitAndAssert('/'); + } + + ['@test Calling transitionTo does not lose query params already on the activeTransition'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + this.route('sibling'); + }); + }); + this.add('route:parent.child', _routing.Route.extend({ + afterModel() { + expectDeprecation(() => { + this.transitionTo('parent.sibling'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.setSingleQPController('parent'); + return this.visit('/parent/child?foo=lol').then(() => { + this.assertCurrentPath('/parent/sibling?foo=lol', 'redirected to the sibling route, instead of child route'); + assert.equal(this.getController('parent').get('foo'), 'lol', 'controller has value from the active transition'); + }); + } + + ['@test Calling transitionTo does not serialize query params already serialized on the activeTransition'](assert) { + assert.expect(4); + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + this.route('sibling'); + }); + }); + this.add('route:parent.child', _routing.Route.extend({ + afterModel() { + expectDeprecation(() => { + this.transitionTo('parent.sibling'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add('controller:parent', _controller.default.extend({ + queryParams: ['array', 'string'], + array: [], + string: '' + })); // `/parent/child?array=["one",2]&string=hello` + + return this.visit('/parent/child?array=%5B%22one%22%2C2%5D&string=hello').then(() => { + this.assertCurrentPath('/parent/sibling?array=%5B%22one%22%2C2%5D&string=hello', 'redirected to the sibling route, instead of child route'); + assert.equal(this.getController('parent').get('string'), 'hello', 'controller has value from the active transition'); + assert.deepEqual(this.getController('parent').get('array'), ['one', 2], 'controller has value from the active transition'); + }); + } + + async ['@test Single query params can be set on the controller and reflected in the url'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.setSingleQPController('home'); + await this.visitAndAssert('/'); + var controller = this.getController('home'); + await this.setAndFlush(controller, 'foo', '456'); + this.assertCurrentPath('/?foo=456'); + await this.setAndFlush(controller, 'foo', '987'); + this.assertCurrentPath('/?foo=987'); + } + + async ['@test Query params can map to different url keys configured on the controller'](assert) { + assert.expect(6); + this.add('controller:index', _controller.default.extend({ + queryParams: [{ + foo: 'other_foo', + bar: { + as: 'other_bar' + } + }], + foo: 'FOO', + bar: 'BAR' + })); + await this.visitAndAssert('/'); + var controller = this.getController('index'); + await this.setAndFlush(controller, 'foo', 'LEX'); + this.assertCurrentPath('/?other_foo=LEX', "QP mapped correctly without 'as'"); + await this.setAndFlush(controller, 'foo', 'WOO'); + this.assertCurrentPath('/?other_foo=WOO', "QP updated correctly without 'as'"); + await this.transitionTo('/?other_foo=NAW'); + assert.equal(controller.get('foo'), 'NAW', 'QP managed correctly on URL transition'); + await this.setAndFlush(controller, 'bar', 'NERK'); + this.assertCurrentPath('/?other_bar=NERK&other_foo=NAW', "QP mapped correctly with 'as'"); + await this.setAndFlush(controller, 'bar', 'NUKE'); + this.assertCurrentPath('/?other_bar=NUKE&other_foo=NAW', "QP updated correctly with 'as'"); + } + + async ['@test Routes have a private overridable serializeQueryParamKey hook'](assert) { + assert.expect(2); + this.add('route:index', _routing.Route.extend({ + serializeQueryParamKey: _string.dasherize + })); + this.setSingleQPController('index', 'funTimes', ''); + await this.visitAndAssert('/'); + var controller = this.getController('index'); + await this.setAndFlush(controller, 'funTimes', 'woot'); + this.assertCurrentPath('/?fun-times=woot'); + } + + async ['@test Can override inherited QP behavior by specifying queryParams as a computed property'](assert) { + assert.expect(3); + this.setSingleQPController('index', 'a', 0, { + queryParams: (0, _metal.computed)(function () { + return ['c']; + }), + c: true + }); + await this.visitAndAssert('/'); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, 'a', 1); + this.assertCurrentPath('/', 'QP did not update due to being overriden'); + await this.setAndFlush(indexController, 'c', false); + this.assertCurrentPath('/?c=false', 'QP updated with overridden param'); + } + + async ['@test Can concatenate inherited QP behavior by specifying queryParams as an array'](assert) { + assert.expect(3); + this.setSingleQPController('index', 'a', 0, { + queryParams: ['c'], + c: true + }); + await this.visitAndAssert('/'); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, 'a', 1); + this.assertCurrentPath('/?a=1', 'Inherited QP did update'); + await this.setAndFlush(indexController, 'c', false); + this.assertCurrentPath('/?a=1&c=false', 'New QP did update'); + } + + ['@test model hooks receives query params'](assert) { + assert.expect(2); + this.setSingleQPController('index'); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + foo: 'bar' + }); + } + + })); + return this.visitAndAssert('/'); + } + + ['@test model hooks receives query params with dynamic segment params'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:id' + }); + }); + this.setSingleQPController('index'); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + foo: 'bar', + id: 'baz' + }); + } + + })); + return this.visitAndAssert('/baz'); + } + + ['@test model hooks receives query params (overridden by incoming url value)'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:id' + }); + }); + this.setSingleQPController('index'); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + foo: 'baz', + id: 'boo' + }); + } + + })); + return this.visitAndAssert('/boo?foo=baz'); + } + + async ['@test error is thrown if dynamic segment and query param have same name'](assert) { + this.router.map(function () { + this.route('index', { + path: '/:foo' + }); + }); + this.setSingleQPController('index'); + await assert.rejectsAssertion(this.visitAndAssert('/boo?foo=baz'), `The route 'index' has both a dynamic segment and query param with name 'foo'. Please rename one to avoid collisions.`); + } + + ['@test query params have been set by the time setupController is called'](assert) { + assert.expect(2); + this.setSingleQPController('application'); + this.add('route:application', _routing.Route.extend({ + setupController(controller) { + assert.equal(controller.get('foo'), 'YEAH', "controller's foo QP property set before setupController called"); + } + + })); + return this.visitAndAssert('/?foo=YEAH'); + } + + ['@test mapped query params have been set by the time setupController is called'](assert) { + assert.expect(2); + this.setSingleQPController('application', { + faz: 'foo' + }); + this.add('route:application', _routing.Route.extend({ + setupController(controller) { + assert.equal(controller.get('faz'), 'YEAH', "controller's foo QP property set before setupController called"); + } + + })); + return this.visitAndAssert('/?foo=YEAH'); + } + + ['@test Route#paramsFor fetches query params with default value'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:something' + }); + }); + this.setSingleQPController('index'); + this.add('route:index', _routing.Route.extend({ + model() + /* params, transition */ + { + assert.deepEqual(this.paramsFor('index'), { + something: 'baz', + foo: 'bar' + }, 'could retrieve params for index'); + } + + })); + return this.visitAndAssert('/baz'); + } + + ['@test Route#paramsFor fetches query params with non-default value'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:something' + }); + }); + this.setSingleQPController('index'); + this.add('route:index', _routing.Route.extend({ + model() + /* params, transition */ + { + assert.deepEqual(this.paramsFor('index'), { + something: 'baz', + foo: 'boo' + }, 'could retrieve params for index'); + } + + })); + return this.visitAndAssert('/baz?foo=boo'); + } + + ['@test Route#paramsFor fetches default falsy query params'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:something' + }); + }); + this.setSingleQPController('index', 'foo', false); + this.add('route:index', _routing.Route.extend({ + model() + /* params, transition */ + { + assert.deepEqual(this.paramsFor('index'), { + something: 'baz', + foo: false + }, 'could retrieve params for index'); + } + + })); + return this.visitAndAssert('/baz'); + } + + ['@test Route#paramsFor fetches non-default falsy query params'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('index', { + path: '/:something' + }); + }); + this.setSingleQPController('index', 'foo', true); + this.add('route:index', _routing.Route.extend({ + model() + /* params, transition */ + { + assert.deepEqual(this.paramsFor('index'), { + something: 'baz', + foo: false + }, 'could retrieve params for index'); + } + + })); + return this.visitAndAssert('/baz?foo=false'); + } + + ['@test model hook can query prefix-less application params'](assert) { + assert.expect(4); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + this.add('route:application', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + appomg: 'applol' + }); + } + + })); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + omg: 'lol' + }); + assert.deepEqual(this.paramsFor('application'), { + appomg: 'applol' + }); + } + + })); + return this.visitAndAssert('/'); + } + + ['@test model hook can query prefix-less application params (overridden by incoming url value)'](assert) { + assert.expect(4); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + this.add('route:application', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + appomg: 'appyes' + }); + } + + })); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + omg: 'yes' + }); + assert.deepEqual(this.paramsFor('application'), { + appomg: 'appyes' + }); + } + + })); + return this.visitAndAssert('/?appomg=appyes&omg=yes'); + } + + async ['@test can opt into full transition by setting refreshModel in route queryParams'](assert) { + assert.expect(7); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + var appModelCount = 0; + this.add('route:application', _routing.Route.extend({ + model() + /* params, transition */ + { + appModelCount++; + } + + })); + var indexModelCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + + model(params) { + indexModelCount++; + + if (indexModelCount === 1) { + assert.deepEqual(params, { + omg: 'lol' + }, 'params are correct on first pass'); + } else if (indexModelCount === 2) { + assert.deepEqual(params, { + omg: 'lex' + }, 'params are correct on second pass'); + } + } + + })); + await this.visitAndAssert('/'); + assert.equal(appModelCount, 1, 'app model hook ran'); + assert.equal(indexModelCount, 1, 'index model hook ran'); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, 'omg', 'lex'); + assert.equal(appModelCount, 1, 'app model hook did not run again'); + assert.equal(indexModelCount, 2, 'index model hook ran again due to refreshModel'); + } + + async ['@test refreshModel and replace work together'](assert) { + assert.expect(8); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + var appModelCount = 0; + this.add('route:application', _routing.Route.extend({ + model() + /* params */ + { + appModelCount++; + } + + })); + var indexModelCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: { + omg: { + refreshModel: true, + replace: true + } + }, + + model(params) { + indexModelCount++; + + if (indexModelCount === 1) { + assert.deepEqual(params, { + omg: 'lol' + }, 'params are correct on first pass'); + } else if (indexModelCount === 2) { + assert.deepEqual(params, { + omg: 'lex' + }, 'params are correct on second pass'); + } + } + + })); + await this.visitAndAssert('/'); + assert.equal(appModelCount, 1, 'app model hook ran'); + assert.equal(indexModelCount, 1, 'index model hook ran'); + var indexController = this.getController('index'); + this.expectedReplaceURL = '/?omg=lex'; + await this.setAndFlush(indexController, 'omg', 'lex'); + assert.equal(appModelCount, 1, 'app model hook did not run again'); + assert.equal(indexModelCount, 2, 'index model hook ran again due to refreshModel'); + } + + async ['@test multiple QP value changes only cause a single model refresh'](assert) { + assert.expect(2); + this.setSingleQPController('index', 'alex', 'lol'); + this.setSingleQPController('index', 'steely', 'lel'); + var refreshCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: { + alex: { + refreshModel: true + }, + steely: { + refreshModel: true + } + }, + + refresh() { + refreshCount++; + } + + })); + await this.visitAndAssert('/'); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, { + alex: 'fran', + steely: 'david' + }); + assert.equal(refreshCount, 1, 'index refresh hook only run once'); + } + + ['@test refreshModel does not cause a second transition during app boot '](assert) { + assert.expect(1); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + this.add('route:index', _routing.Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + + refresh() { + assert.ok(false); + } + + })); + return this.visitAndAssert('/?appomg=hello&omg=world'); + } + + async ['@test queryParams are updated when a controller property is set and the route is refreshed. Issue #13263 '](assert) { + this.addTemplate('application', '{{this.foo}}{{outlet}}'); + this.setSingleQPController('application', 'foo', 1, { + actions: { + increment() { + this.incrementProperty('foo'); + this.send('refreshRoute'); + } + + } + }); + this.add('route:application', _routing.Route.extend({ + actions: { + refreshRoute() { + this.refresh(); + } + + } + })); + await this.visitAndAssert('/'); + assert.equal((0, _internalTestHelpers.getTextOf)(document.getElementById('test-value')), '1'); + document.getElementById('test-button').click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal((0, _internalTestHelpers.getTextOf)(document.getElementById('test-value')), '2'); + this.assertCurrentPath('/?foo=2'); + document.getElementById('test-button').click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal((0, _internalTestHelpers.getTextOf)(document.getElementById('test-value')), '3'); + this.assertCurrentPath('/?foo=3'); + } + + async ["@test Use Ember.get to retrieve query params 'refreshModel' configuration"](assert) { + assert.expect(7); + this.setSingleQPController('application', 'appomg', 'applol'); + this.setSingleQPController('index', 'omg', 'lol'); + var appModelCount = 0; + this.add('route:application', _routing.Route.extend({ + model() + /* params */ + { + appModelCount++; + } + + })); + var indexModelCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: _runtime.Object.create({ + unknownProperty() { + return { + refreshModel: true + }; + } + + }), + + model(params) { + indexModelCount++; + + if (indexModelCount === 1) { + assert.deepEqual(params, { + omg: 'lol' + }); + } else if (indexModelCount === 2) { + assert.deepEqual(params, { + omg: 'lex' + }); + } + } + + })); + await this.visitAndAssert('/'); + assert.equal(appModelCount, 1); + assert.equal(indexModelCount, 1); + var indexController = this.getController('index'); + await this.setAndFlush(indexController, 'omg', 'lex'); + assert.equal(appModelCount, 1); + assert.equal(indexModelCount, 2); + } + + async ['@test can use refreshModel even with URL changes that remove QPs from address bar'](assert) { + assert.expect(4); + this.setSingleQPController('index', 'omg', 'lol'); + var indexModelCount = 0; + this.add('route:index', _routing.Route.extend({ + queryParams: { + omg: { + refreshModel: true + } + }, + + model(params) { + indexModelCount++; + var data; + + if (indexModelCount === 1) { + data = 'foo'; + } else if (indexModelCount === 2) { + data = 'lol'; + } + + assert.deepEqual(params, { + omg: data + }, 'index#model receives right data'); + } + + })); + await this.visitAndAssert('/?omg=foo'); + await this.transitionTo('/'); + var indexController = this.getController('index'); + assert.equal(indexController.get('omg'), 'lol'); + } + + async ['@test can opt into a replace query by specifying replace:true in the Route config hash'](assert) { + assert.expect(2); + this.setSingleQPController('application', 'alex', 'matchneer'); + this.add('route:application', _routing.Route.extend({ + queryParams: { + alex: { + replace: true + } + } + })); + await this.visitAndAssert('/'); + var appController = this.getController('application'); + this.expectedReplaceURL = '/?alex=wallace'; + await this.setAndFlush(appController, 'alex', 'wallace'); + } + + async ['@test Route query params config can be configured using property name instead of URL key'](assert) { + assert.expect(2); + this.add('controller:application', _controller.default.extend({ + queryParams: [{ + commitBy: 'commit_by' + }] + })); + this.add('route:application', _routing.Route.extend({ + queryParams: { + commitBy: { + replace: true + } + } + })); + await this.visitAndAssert('/'); + var appController = this.getController('application'); + this.expectedReplaceURL = '/?commit_by=igor_seb'; + await this.setAndFlush(appController, 'commitBy', 'igor_seb'); + } + + async ['@test An explicit replace:false on a changed QP always wins and causes a pushState'](assert) { + assert.expect(3); + this.add('controller:application', _controller.default.extend({ + queryParams: ['alex', 'steely'], + alex: 'matchneer', + steely: 'dan' + })); + this.add('route:application', _routing.Route.extend({ + queryParams: { + alex: { + replace: true + }, + steely: { + replace: false + } + } + })); + await this.visit('/'); + var appController = this.getController('application'); + this.expectedPushURL = '/?alex=wallace&steely=jan'; + await this.setAndFlush(appController, { + alex: 'wallace', + steely: 'jan' + }); + this.expectedPushURL = '/?alex=wallace&steely=fran'; + await this.setAndFlush(appController, { + steely: 'fran' + }); + this.expectedReplaceURL = '/?alex=sriracha&steely=fran'; + await this.setAndFlush(appController, 'alex', 'sriracha'); + } + + async ['@test can opt into full transition by setting refreshModel in route queryParams when transitioning from child to parent'](assert) { + this.addTemplate('parent', '{{outlet}}'); + this.addTemplate('parent.child', "Parent"); + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + }); + }); + var parentModelCount = 0; + this.add('route:parent', class extends _routing.Route { + constructor(...args) { + super(...args); + this.queryParams = { + foo: { + refreshModel: true + } + }; + } + + model() { + parentModelCount++; + } + + }); + this.setSingleQPController('parent', 'foo', 'abc'); + await this.visit('/parent/child?foo=lol'); + assert.equal(parentModelCount, 1); + (0, _runloop.run)(document.getElementById('parent-link'), 'click'); + assert.equal(parentModelCount, 2); + } + + async ["@test Use Ember.get to retrieve query params 'replace' configuration"](assert) { + assert.expect(2); + this.setSingleQPController('application', 'alex', 'matchneer'); + this.add('route:application', _routing.Route.extend({ + queryParams: _runtime.Object.create({ + unknownProperty() + /* keyName */ + { + // We are simulating all qps requiring refresh + return { + replace: true + }; + } + + }) + })); + await this.visitAndAssert('/'); + var appController = this.getController('application'); + this.expectedReplaceURL = '/?alex=wallace'; + await this.setAndFlush(appController, 'alex', 'wallace'); + } + + async ['@test can override incoming QP values in setupController'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('about'); + }); + this.setSingleQPController('index', 'omg', 'lol'); + this.add('route:index', _routing.Route.extend({ + setupController(controller) { + assert.ok(true, 'setupController called'); + controller.set('omg', 'OVERRIDE'); + }, + + actions: { + queryParamsDidChange() { + assert.ok(false, "queryParamsDidChange shouldn't fire"); + } + + } + })); + await this.visitAndAssert('/about'); + await this.transitionTo('index'); + this.assertCurrentPath('/?omg=OVERRIDE'); + } + + async ['@test can override incoming QP array values in setupController'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('about'); + }); + this.setSingleQPController('index', 'omg', ['lol']); + this.add('route:index', _routing.Route.extend({ + setupController(controller) { + assert.ok(true, 'setupController called'); + controller.set('omg', ['OVERRIDE']); + }, + + actions: { + queryParamsDidChange() { + assert.ok(false, "queryParamsDidChange shouldn't fire"); + } + + } + })); + await this.visitAndAssert('/about'); + await this.transitionTo('index'); + this.assertCurrentPath('/?omg=' + encodeURIComponent(JSON.stringify(['OVERRIDE']))); + } + + ['@test URL transitions that remove QPs still register as QP changes'](assert) { + assert.expect(2); + this.setSingleQPController('index', 'omg', 'lol'); + return this.visit('/?omg=borf').then(() => { + var indexController = this.getController('index'); + assert.equal(indexController.get('omg'), 'borf'); + this.transitionTo('/'); + assert.equal(indexController.get('omg'), 'lol'); + }); + } + + async ['@test Subresource naming style is supported'](assert) { + this.router.map(function () { + this.route('abc.def', { + path: '/abcdef' + }, function () { + this.route('zoo'); + }); + }); + this.addTemplate('application', ` + A + B + {{outlet}} + `); + this.setSingleQPController('abc.def', 'foo', 'lol'); + this.setSingleQPController('abc.def.zoo', 'bar', 'haha'); + await this.visitAndAssert('/'); + assert.equal(this.$('#one').attr('href'), '/abcdef?foo=123'); + assert.equal(this.$('#two').attr('href'), '/abcdef/zoo?bar=456&foo=123'); + (0, _runloop.run)(this.$('#one'), 'click'); + this.assertCurrentPath('/abcdef?foo=123'); + (0, _runloop.run)(this.$('#two'), 'click'); + this.assertCurrentPath('/abcdef/zoo?bar=456&foo=123'); + } + + async ['@test transitionTo supports query params']() { + this.setSingleQPController('index', 'foo', 'lol'); + await this.visitAndAssert('/'); + await this.transitionTo({ + queryParams: { + foo: 'borf' + } + }); + this.assertCurrentPath('/?foo=borf', 'shorthand supported'); + await this.transitionTo({ + queryParams: { + 'index:foo': 'blaf' + } + }); + this.assertCurrentPath('/?foo=blaf', 'longform supported'); + await this.transitionTo({ + queryParams: { + 'index:foo': false + } + }); + this.assertCurrentPath('/?foo=false', 'longform supported (bool)'); + await this.transitionTo({ + queryParams: { + foo: false + } + }); + this.assertCurrentPath('/?foo=false', 'shorhand supported (bool)'); + } + + async ['@test transitionTo supports query params (multiple)']() { + this.add('controller:index', _controller.default.extend({ + queryParams: ['foo', 'bar'], + foo: 'lol', + bar: 'wat' + })); + await this.visitAndAssert('/'); + await this.transitionTo({ + queryParams: { + foo: 'borf' + } + }); + this.assertCurrentPath('/?foo=borf', 'shorthand supported'); + await this.transitionTo({ + queryParams: { + 'index:foo': 'blaf' + } + }); + this.assertCurrentPath('/?foo=blaf', 'longform supported'); + await this.transitionTo({ + queryParams: { + 'index:foo': false + } + }); + this.assertCurrentPath('/?foo=false', 'longform supported (bool)'); + await this.transitionTo({ + queryParams: { + foo: false + } + }); + this.assertCurrentPath('/?foo=false', 'shorhand supported (bool)'); + } + + async ["@test setting controller QP to empty string doesn't generate null in URL"](assert) { + assert.expect(1); + this.setSingleQPController('index', 'foo', '123'); + await this.visit('/'); + var controller = this.getController('index'); + this.expectedPushURL = '/?foo='; + await this.setAndFlush(controller, 'foo', ''); + } + + async ["@test setting QP to empty string doesn't generate null in URL"](assert) { + assert.expect(1); + this.add('route:index', _routing.Route.extend({ + queryParams: { + foo: { + defaultValue: '123' + } + } + })); + await this.visit('/'); + var controller = this.getController('index'); + this.expectedPushURL = '/?foo='; + await this.setAndFlush(controller, 'foo', ''); + } + + ['@test A default boolean value deserializes QPs as booleans rather than strings'](assert) { + assert.expect(3); + this.setSingleQPController('index', 'foo', false); + this.add('route:index', _routing.Route.extend({ + model(params) { + assert.equal(params.foo, true, 'model hook received foo as boolean true'); + } + + })); + return this.visit('/?foo=true').then(() => { + var controller = this.getController('index'); + assert.equal(controller.get('foo'), true); + this.transitionTo('/?foo=false'); + assert.equal(controller.get('foo'), false); + }); + } + + ['@test Query param without value are empty string'](assert) { + assert.expect(1); + this.add('controller:index', _controller.default.extend({ + queryParams: ['foo'], + foo: '' + })); + return this.visit('/?foo=').then(() => { + var controller = this.getController('index'); + assert.equal(controller.get('foo'), ''); + }); + } + + async ['@test Array query params can be set'](assert) { + assert.expect(2); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.setSingleQPController('home', 'foo', []); + await this.visit('/'); + var controller = this.getController('home'); + await this.setAndFlush(controller, 'foo', [1, 2]); + this.assertCurrentPath('/?foo=%5B1%2C2%5D'); + await this.setAndFlush(controller, 'foo', [3, 4]); + this.assertCurrentPath('/?foo=%5B3%2C4%5D'); + } + + async ['@test (de)serialization: arrays'](assert) { + assert.expect(4); + this.setSingleQPController('index', 'foo', [1]); + await this.visitAndAssert('/'); + await this.transitionTo({ + queryParams: { + foo: [2, 3] + } + }); + this.assertCurrentPath('/?foo=%5B2%2C3%5D', 'shorthand supported'); + await this.transitionTo({ + queryParams: { + 'index:foo': [4, 5] + } + }); + this.assertCurrentPath('/?foo=%5B4%2C5%5D', 'longform supported'); + await this.transitionTo({ + queryParams: { + foo: [] + } + }); + this.assertCurrentPath('/?foo=%5B%5D', 'longform supported'); + } + + ['@test Url with array query param sets controller property to array'](assert) { + assert.expect(1); + this.setSingleQPController('index', 'foo', ''); + return this.visit('/?foo[]=1&foo[]=2&foo[]=3').then(() => { + var controller = this.getController('index'); + assert.deepEqual(controller.get('foo'), ['1', '2', '3']); + }); + } + + async ['@test Array query params can be pushed/popped'](assert) { + assert.expect(17); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.setSingleQPController('home', 'foo', (0, _runtime.A)()); + await this.visitAndAssert('/'); + var controller = this.getController('home'); + controller.foo.pushObject(1); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); + controller.foo.popObject(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/'); + assert.deepEqual(controller.foo, []); + controller.foo.pushObject(1); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); + controller.foo.popObject(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/'); + assert.deepEqual(controller.foo, []); + controller.foo.pushObject(1); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); + controller.foo.pushObject(2); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B1%2C2%5D'); + assert.deepEqual(controller.foo, [1, 2]); + controller.foo.popObject(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B1%5D'); + assert.deepEqual(controller.foo, [1]); + controller.foo.unshiftObject('lol'); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B%22lol%22%2C1%5D'); + assert.deepEqual(controller.foo, ['lol', 1]); + } + + async ["@test Overwriting with array with same content shouldn't refire update"](assert) { + assert.expect(4); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + var modelCount = 0; + this.add('route:home', _routing.Route.extend({ + model() { + modelCount++; + } + + })); + this.setSingleQPController('home', 'foo', (0, _runtime.A)([1])); + await this.visitAndAssert('/'); + assert.equal(modelCount, 1); + var controller = this.getController('home'); + await this.setAndFlush(controller, 'model', (0, _runtime.A)([1])); + assert.equal(modelCount, 1); + this.assertCurrentPath('/'); + } + + ['@test Defaulting to params hash as the model should not result in that params object being watched'](assert) { + assert.expect(1); + this.router.map(function () { + this.route('other'); + }); // This causes the params hash, which is returned as a route's + // model if no other model could be resolved given the provided + // params (and no custom model hook was defined), to be watched, + // unless we return a copy of the params hash. + + this.setSingleQPController('application', 'woot', 'wat'); + this.add('route:other', _routing.Route.extend({ + model(p, trans) { + var m = (0, _meta.peekMeta)(trans[_router_js.PARAMS_SYMBOL].application); + assert.ok(m === null, "A meta object isn't constructed for this params POJO"); + } + + })); + return this.visit('/').then(() => { + return this.transitionTo('other'); + }); + } + + async ['@test Setting bound query param property to null or undefined does not serialize to url'](assert) { + assert.expect(9); + this.router.map(function () { + this.route('home'); + }); + this.setSingleQPController('home', 'foo', [1, 2]); + await this.visitAndAssert('/home'); + var controller = this.getController('home'); + assert.deepEqual(controller.get('foo'), [1, 2]); + this.assertCurrentPath('/home'); + await this.setAndFlush(controller, 'foo', (0, _runtime.A)([1, 3])); + this.assertCurrentPath('/home?foo=%5B1%2C3%5D'); + await this.transitionTo('/home'); + assert.deepEqual(controller.get('foo'), [1, 2]); + this.assertCurrentPath('/home'); + await this.setAndFlush(controller, 'foo', null); + this.assertCurrentPath('/home', 'Setting property to null'); + await this.setAndFlush(controller, 'foo', (0, _runtime.A)([1, 3])); + this.assertCurrentPath('/home?foo=%5B1%2C3%5D'); + await this.setAndFlush(controller, 'foo', undefined); + this.assertCurrentPath('/home', 'Setting property to undefined'); + } + + async ['@test with null or undefined QPs does not get serialized into url'](assert) { + this.addTemplate('home', ` + Home + Home + `); + this.router.map(function () { + this.route('home'); + }); + this.setSingleQPController('home', 'foo', [], { + nullValue: null, + undefinedValue: undefined + }); + await this.visitAndAssert('/home'); + assert.equal(this.$('#null-link').attr('href'), '/home'); + assert.equal(this.$('#undefined-link').attr('href'), '/home'); + } + + ["@test A child of a resource route still defaults to parent route's model even if the child route has a query param"](assert) { + assert.expect(2); + this.setSingleQPController('index', 'woot', undefined, { + woot: undefined + }); + this.add('route:application', _routing.Route.extend({ + model() + /* p, trans */ + { + return { + woot: true + }; + } + + })); + this.add('route:index', _routing.Route.extend({ + setupController(controller, model) { + assert.deepEqual(model, { + woot: true + }, 'index route inherited model route from parent route'); + } + + })); + return this.visitAndAssert('/'); + } + + async ['@test opting into replace does not affect transitions between routes']() { + this.addTemplate('application', ` + Foo + Bar + Bar + {{outlet}} + `); + this.router.map(function () { + this.route('foo'); + this.route('bar'); + }); + this.setSingleQPController('bar', 'raytiley', 'israd'); + this.add('route:bar', class extends _routing.Route { + constructor(...args) { + super(...args); + this.queryParams = { + raytiley: { + replace: true + } + }; + } + + }); + await this.visit('/'); + var controller = this.getController('bar'); + this.expectedPushURL = '/foo'; + (0, _runloop.run)(document.getElementById('foo-link'), 'click'); + this.expectedPushURL = '/bar'; + (0, _runloop.run)(document.getElementById('bar-no-qp-link'), 'click'); + this.expectedReplaceURL = '/bar?raytiley=woot'; + await this.setAndFlush(controller, 'raytiley', 'woot'); + this.expectedPushURL = '/foo'; + (0, _runloop.run)(document.getElementById('foo-link'), 'click'); + this.expectedPushURL = '/bar?raytiley=isthebest'; + (0, _runloop.run)(document.getElementById('bar-link'), 'click'); + } + + async ["@test undefined isn't serialized or deserialized into a string"](assert) { + this.router.map(function () { + this.route('example'); + }); + this.addTemplate('application', "Example"); + this.setSingleQPController('example', 'foo', undefined, { + foo: undefined + }); + var entered = 0; + this.add('route:example', class extends _routing.Route { + model(params) { + entered++; + assert.deepEqual(params, { + foo: undefined + }); + } + + }); + await this.visitAndAssert('/'); + assert.equal(this.$('#the-link').attr('href'), '/example', 'renders without undefined qp serialized'); + await this.transitionTo('example', { + queryParams: { + foo: undefined + } + }); + assert.equal(entered, 1, 'Should have entered example route'); + this.assertCurrentPath('/example'); + } + + ['@test when refreshModel is true and loading hook is undefined, model hook will rerun when QPs change even if previous did not finish']() { + return this.refreshModelWhileLoadingTest(); + } + + ['@test when refreshModel is true and loading hook returns false, model hook will rerun when QPs change even if previous did not finish']() { + return this.refreshModelWhileLoadingTest(false); + } + + ['@test when refreshModel is true and loading hook returns true, model hook will rerun when QPs change even if previous did not finish']() { + return this.refreshModelWhileLoadingTest(true); + } + + async ["@test warn user that Route's queryParams configuration must be an Object, not an Array"](assert) { + assert.expect(1); + this.add('route:application', _routing.Route.extend({ + queryParams: [{ + commitBy: { + replace: true + } + }] + })); + await assert.rejectsAssertion(this.visit('/'), 'You passed in `[{"commitBy":{"replace":true}}]` as the value for `queryParams` but `queryParams` cannot be an Array'); + } + + async ['@test handle route names that clash with Object.prototype properties'](assert) { + assert.expect(1); + this.router.map(function () { + this.route('constructor'); + }); + this.add('route:constructor', _routing.Route.extend({ + queryParams: { + foo: { + defaultValue: '123' + } + } + })); + await this.visit('/'); + await this.transitionTo('constructor', { + queryParams: { + foo: '999' + } + }); + var controller = this.getController('constructor'); + assert.equal((0, _metal.get)(controller, 'foo'), '999'); + } + + async ['@test Single query params defined with tracked properties can be on the controller and reflected in the url'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.add(`controller:home`, _controller.default.extend({ + queryParams: ['foo'], + foo: (0, _metal.tracked)() + })); + await this.visitAndAssert('/'); + var controller = this.getController('home'); + controller.foo = '456'; + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=456'); + controller.foo = '987'; + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=987'); + } + + async ['@test Single query params defined with tracked properties can be linked to (and log is present)'](assert) { + var _class3, _descriptor, _descriptor2; + + assert.expect(3); + this.addTemplate('application', ` + + Home + + + 'Home (with params)' + + + + {{log this.foo}} + `); + this.add(`controller:application`, (_class3 = class _class3 extends _controller.default { + constructor(...args) { + super(...args); + this.queryParams = ['foo', 'bar']; + + _initializerDefineProperty(this, "foo", _descriptor, this); + + _initializerDefineProperty(this, "bar", _descriptor2, this); + } + + }, (_descriptor = _applyDecoratedDescriptor(_class3.prototype, "foo", [_metal.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return []; + } + }), _descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "bar", [_metal.tracked], { + configurable: true, + enumerable: true, + writable: true, + initializer: function () { + return []; + } + })), _class3)); + await this.visitAndAssert('/'); + document.getElementById('the-link').click(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/'); + document.getElementById('the-link-with-params').click(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=%5B123%5D'); + } + + async ['@test Single query params defined with native getters and tracked properties can be on the controller and reflected in the url'](assert) { + assert.expect(3); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + this.add(`controller:home`, _controller.default.extend({ + queryParams: ['foo'], + + get foo() { + return this.bar; + }, + + set foo(value) { + this.bar = value; + }, + + bar: (0, _metal.tracked)() + })); + await this.visitAndAssert('/'); + var controller = this.getController('home'); + controller.bar = '456'; + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=456'); + controller.bar = '987'; + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/?foo=987'); + } + + async [`@test Updating single query parameter doesn't affect other query parameters. Issue #14438`](assert) { + assert.expect(6); + this.router.map(function () { + this.route('grandparent', { + path: 'grandparent/:foo' + }, function () { + this.route('parent', function () { + this.route('child'); + }); + }); + }); + this.addTemplate('grandparent.parent.loading', 'Loading...'); + this.add('route:index', _routing.Route.extend({ + redirect() { + expectDeprecation(() => { + this.transitionTo('grandparent.parent.child', 1); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add('route:grandparent.parent.child', _routing.Route.extend({ + model() { + return Promise.resolve(); + } + + })); + this.add('controller:grandparent.parent', _controller.default.extend({ + queryParams: ['foo', 'bar'], + foo: 'FOO', + bar: 'BAR' + })); + await this.visit('/'); + this.assertCurrentPath('/grandparent/1/parent/child'); + var parentController = this.getController('grandparent.parent'); + await this.setAndFlush(parentController, 'foo', 'NEW_FOO'); + assert.equal(parentController.foo, 'NEW_FOO'); + this.assertCurrentPath('/grandparent/1/parent/child?foo=NEW_FOO'); + await this.setAndFlush(parentController, 'bar', 'NEW_BAR'); + assert.equal(parentController.bar, 'NEW_BAR'); + this.assertCurrentPath('/grandparent/1/parent/child?bar=NEW_BAR&foo=NEW_FOO'); + } + + }); +}); +define("ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test", ["@ember/controller", "@ember/-internals/runtime", "@ember/-internals/routing", "@ember/-internals/metal", "internal-test-helpers"], function (_controller, _runtime, _routing, _metal, _internalTestHelpers) { + "use strict"; + + class ModelDependentQPTestCase extends _internalTestHelpers.QueryParamTestCase { + boot() { + this.setupApplication(); + return this.visitApplication(); + } + + teardown() { + super.teardown(...arguments); + this.assert.ok(!this.expectedModelHookParams, 'there should be no pending expectation of expected model hook params'); + } + + reopenController(name, options) { + this.application.resolveRegistration(`controller:${name}`).reopen(options); + } + + reopenRoute(name, options) { + this.application.resolveRegistration(`route:${name}`).reopen(options); + } + + async queryParamsStickyTest1(urlPrefix) { + var assert = this.assert; + assert.expect(14); + await this.boot(); + this.$link1.click(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath(`${urlPrefix}/a-1`); + await this.setAndFlush(this.controller, 'q', 'lol'); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + this.$link2.click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal(this.controller.get('q'), 'wat'); + assert.equal(this.controller.get('z'), 0); + assert.deepEqual(this.controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + } + + async queryParamsStickyTest2(urlPrefix) { + var assert = this.assert; + assert.expect(24); + await this.boot(); + this.expectedModelHookParams = { + id: 'a-1', + q: 'lol', + z: 0 + }; + await this.transitionTo(`${urlPrefix}/a-1?q=lol`); + assert.deepEqual(this.controller.get('model'), { + id: 'a-1' + }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + this.expectedModelHookParams = { + id: 'a-2', + q: 'lol', + z: 0 + }; + await this.transitionTo(`${urlPrefix}/a-2?q=lol`); + assert.deepEqual(this.controller.get('model'), { + id: 'a-2' + }, "controller's model changed to a-2"); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + this.expectedModelHookParams = { + id: 'a-3', + q: 'lol', + z: 123 + }; + await this.transitionTo(`${urlPrefix}/a-3?q=lol&z=123`); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 123); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=lol&z=123`); + } + + async queryParamsStickyTest3(urlPrefix, articleLookup) { + var assert = this.assert; + assert.expect(32); + this.addTemplate('application', ` + {{#each articles as |a|}} + Article + {{/each}} + `); + await this.boot(); + this.expectedModelHookParams = { + id: 'a-1', + q: 'wat', + z: 0 + }; + await this.transitionTo(articleLookup, 'a-1'); + assert.deepEqual(this.controller.get('model'), { + id: 'a-1' + }); + assert.equal(this.controller.get('q'), 'wat'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + this.expectedModelHookParams = { + id: 'a-2', + q: 'lol', + z: 0 + }; + await this.transitionTo(articleLookup, 'a-2', { + queryParams: { + q: 'lol' + } + }); + assert.deepEqual(this.controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3`); + this.expectedModelHookParams = { + id: 'a-3', + q: 'hay', + z: 0 + }; + await this.transitionTo(articleLookup, 'a-3', { + queryParams: { + q: 'hay' + } + }); + assert.deepEqual(this.controller.get('model'), { + id: 'a-3' + }); + assert.equal(this.controller.get('q'), 'hay'); + assert.equal(this.controller.get('z'), 0); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=hay`); + this.expectedModelHookParams = { + id: 'a-2', + q: 'lol', + z: 1 + }; + await this.transitionTo(articleLookup, 'a-2', { + queryParams: { + z: 1 + } + }); + assert.deepEqual(this.controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 1); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol&z=1`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=hay`); + } + + async queryParamsStickyTest4(urlPrefix, articleLookup) { + var assert = this.assert; + assert.expect(24); + this.setupApplication(); + this.reopenController(articleLookup, { + queryParams: { + q: { + scope: 'controller' + } + } + }); + await this.visitApplication(); + this.$link1.click(); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath(`${urlPrefix}/a-1`); + await this.setAndFlush(this.controller, 'q', 'lol'); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=lol`); + this.$link2.click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal(this.controller.get('q'), 'lol'); + assert.equal(this.controller.get('z'), 0); + assert.deepEqual(this.controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=lol`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=lol`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=lol`); + this.expectedModelHookParams = { + id: 'a-3', + q: 'haha', + z: 123 + }; + await this.transitionTo(`${urlPrefix}/a-3?q=haha&z=123`); + assert.deepEqual(this.controller.get('model'), { + id: 'a-3' + }); + assert.equal(this.controller.get('q'), 'haha'); + assert.equal(this.controller.get('z'), 123); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=haha`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=haha`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=haha&z=123`); + await this.setAndFlush(this.controller, 'q', 'woot'); + assert.equal(this.$link1.getAttribute('href'), `${urlPrefix}/a-1?q=woot`); + assert.equal(this.$link2.getAttribute('href'), `${urlPrefix}/a-2?q=woot`); + assert.equal(this.$link3.getAttribute('href'), `${urlPrefix}/a-3?q=woot&z=123`); + } + + async queryParamsStickyTest5(urlPrefix, commentsLookupKey) { + var assert = this.assert; + assert.expect(12); + await this.boot(); + await this.transitionTo(commentsLookupKey, 'a-1'); + var commentsCtrl = this.getController(commentsLookupKey); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); + await this.setAndFlush(commentsCtrl, 'page', 2); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=2`); + await this.setAndFlush(commentsCtrl, 'page', 3); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=3`); + await this.transitionTo(commentsLookupKey, 'a-2'); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-2/comments`); + await this.transitionTo(commentsLookupKey, 'a-1'); + assert.equal(commentsCtrl.get('page'), 3); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=3`); + } + + async queryParamsStickyTest6(urlPrefix, articleLookup, commentsLookup) { + var assert = this.assert; + assert.expect(13); + this.setupApplication(); + this.reopenRoute(articleLookup, { + resetController(controller, isExiting) { + this.controllerFor(commentsLookup).set('page', 1); + + if (isExiting) { + controller.set('q', 'imdone'); + } + } + + }); + this.addTemplate('about', ` + A + B + `); + await this.visitApplication(); + await this.transitionTo(commentsLookup, 'a-1'); + var commentsCtrl = this.getController(commentsLookup); + assert.equal(commentsCtrl.get('page'), 1); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); + await this.setAndFlush(commentsCtrl, 'page', 2); + this.assertCurrentPath(`${urlPrefix}/a-1/comments?page=2`); + await this.transitionTo(commentsLookup, 'a-2'); + assert.equal(commentsCtrl.get('page'), 1); + assert.equal(this.controller.get('q'), 'wat'); + await this.transitionTo(commentsLookup, 'a-1'); + this.assertCurrentPath(`${urlPrefix}/a-1/comments`); + assert.equal(commentsCtrl.get('page'), 1); + await this.transitionTo('about'); + assert.equal(document.getElementById('one').getAttribute('href'), `${urlPrefix}/a-1/comments?q=imdone`); + assert.equal(document.getElementById('two').getAttribute('href'), `${urlPrefix}/a-2/comments`); + } + + } + + (0, _internalTestHelpers.moduleFor)('Query Params - model-dependent state', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function () { + this.route('article', { + path: '/a/:id' + }, function () { + this.route('comments', { + resetNamespace: true + }); + }); + this.route('about'); + }); + var articles = (0, _runtime.A)([{ + id: 'a-1' + }, { + id: 'a-2' + }, { + id: 'a-3' + }]); + this.add('controller:application', _controller.default.extend({ + articles + })); + var self = this; + var assert = this.assert; + this.add('route:article', _routing.Route.extend({ + model(params) { + if (self.expectedModelHookParams) { + assert.deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); + self.expectedModelHookParams = null; + } + + return articles.findBy('id', params.id); + } + + })); + this.add('controller:article', _controller.default.extend({ + queryParams: ['q', 'z'], + q: 'wat', + z: 0 + })); + this.add('controller:comments', _controller.default.extend({ + queryParams: 'page', + page: 1 + })); + this.addTemplate('application', ` + {{#each this.articles as |a|}} + Article + {{/each}} + {{outlet}} + `); + } + + visitApplication() { + return this.visit('/').then(() => { + var assert = this.assert; + this.$link1 = document.getElementById('a-1'); + this.$link2 = document.getElementById('a-2'); + this.$link3 = document.getElementById('a-3'); + assert.equal(this.$link1.getAttribute('href'), '/a/a-1'); + assert.equal(this.$link2.getAttribute('href'), '/a/a-2'); + assert.equal(this.$link3.getAttribute('href'), '/a/a-3'); + this.controller = this.getController('article'); + }); + } + + ["@test query params have 'model' stickiness by default"]() { + return this.queryParamsStickyTest1('/a'); + } + + ["@test query params have 'model' stickiness by default (url changes)"]() { + return this.queryParamsStickyTest2('/a'); + } + + ["@test query params have 'model' stickiness by default (params-based transitions)"]() { + return this.queryParamsStickyTest3('/a', 'article'); + } + + ["@test 'controller' stickiness shares QP state between models"]() { + return this.queryParamsStickyTest4('/a', 'article'); + } + + ["@test 'model' stickiness is scoped to current or first dynamic parent route"]() { + return this.queryParamsStickyTest5('/a', 'comments'); + } + + ['@test can reset query params using the resetController hook']() { + return this.queryParamsStickyTest6('/a', 'article', 'comments'); + } + + }); + (0, _internalTestHelpers.moduleFor)('Query Params - model-dependent state (nested)', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function () { + this.route('site', function () { + this.route('article', { + path: '/a/:id' + }, function () { + this.route('comments'); + }); + }); + this.route('about'); + }); + var site_articles = (0, _runtime.A)([{ + id: 'a-1' + }, { + id: 'a-2' + }, { + id: 'a-3' + }]); + this.add('controller:application', _controller.default.extend({ + articles: site_articles + })); + var self = this; + var assert = this.assert; + this.add('route:site.article', _routing.Route.extend({ + model(params) { + if (self.expectedModelHookParams) { + assert.deepEqual(params, self.expectedModelHookParams, 'the ArticleRoute model hook received the expected merged dynamic segment + query params hash'); + self.expectedModelHookParams = null; + } + + return site_articles.findBy('id', params.id); + } + + })); + this.add('controller:site.article', _controller.default.extend({ + queryParams: ['q', 'z'], + q: 'wat', + z: 0 + })); + this.add('controller:site.article.comments', _controller.default.extend({ + queryParams: 'page', + page: 1 + })); + this.addTemplate('application', ` + {{#each this.articles as |a|}} + Article + {{/each}} + {{outlet}} + `); + } + + visitApplication() { + return this.visit('/').then(() => { + var assert = this.assert; + this.$link1 = document.getElementById('a-1'); + this.$link2 = document.getElementById('a-2'); + this.$link3 = document.getElementById('a-3'); + assert.equal(this.$link1.getAttribute('href'), '/site/a/a-1'); + assert.equal(this.$link2.getAttribute('href'), '/site/a/a-2'); + assert.equal(this.$link3.getAttribute('href'), '/site/a/a-3'); + this.controller = this.getController('site.article'); + }); + } + + ["@test query params have 'model' stickiness by default"]() { + return this.queryParamsStickyTest1('/site/a'); + } + + ["@test query params have 'model' stickiness by default (url changes)"]() { + return this.queryParamsStickyTest2('/site/a'); + } + + ["@test query params have 'model' stickiness by default (params-based transitions)"]() { + return this.queryParamsStickyTest3('/site/a', 'site.article'); + } + + ["@test 'controller' stickiness shares QP state between models"]() { + return this.queryParamsStickyTest4('/site/a', 'site.article'); + } + + ["@test 'model' stickiness is scoped to current or first dynamic parent route"]() { + return this.queryParamsStickyTest5('/site/a', 'site.article.comments'); + } + + ['@test can reset query params using the resetController hook']() { + return this.queryParamsStickyTest6('/site/a', 'site.article', 'site.article.comments'); + } + + }); + (0, _internalTestHelpers.moduleFor)('Query Params - model-dependent state (nested & more than 1 dynamic segment)', class extends ModelDependentQPTestCase { + setupApplication() { + this.router.map(function () { + this.route('site', { + path: '/site/:site_id' + }, function () { + this.route('article', { + path: '/a/:article_id' + }, function () { + this.route('comments'); + }); + }); + }); + var sites = (0, _runtime.A)([{ + id: 's-1' + }, { + id: 's-2' + }, { + id: 's-3' + }]); + var site_articles = (0, _runtime.A)([{ + id: 'a-1' + }, { + id: 'a-2' + }, { + id: 'a-3' + }]); + this.add('controller:application', _controller.default.extend({ + siteArticles: site_articles, + sites, + allSitesAllArticles: (0, _metal.computed)({ + get() { + var ret = []; + var siteArticles = this.siteArticles; + var sites = this.sites; + sites.forEach(site => { + ret = ret.concat(siteArticles.map(article => { + return { + id: `${site.id}-${article.id}`, + site_id: site.id, + article_id: article.id + }; + })); + }); + return ret; + } + + }) + })); + var self = this; + var assert = this.assert; + this.add('route:site', _routing.Route.extend({ + model(params) { + if (self.expectedSiteModelHookParams) { + assert.deepEqual(params, self.expectedSiteModelHookParams, 'the SiteRoute model hook received the expected merged dynamic segment + query params hash'); + self.expectedSiteModelHookParams = null; + } + + return sites.findBy('id', params.site_id); + } + + })); + this.add('route:site.article', _routing.Route.extend({ + model(params) { + if (self.expectedArticleModelHookParams) { + assert.deepEqual(params, self.expectedArticleModelHookParams, 'the SiteArticleRoute model hook received the expected merged dynamic segment + query params hash'); + self.expectedArticleModelHookParams = null; + } + + return site_articles.findBy('id', params.article_id); + } + + })); + this.add('controller:site', _controller.default.extend({ + queryParams: ['country'], + country: 'au' + })); + this.add('controller:site.article', _controller.default.extend({ + queryParams: ['q', 'z'], + q: 'wat', + z: 0 + })); + this.add('controller:site.article.comments', _controller.default.extend({ + queryParams: ['page'], + page: 1 + })); + this.addTemplate('application', ` + {{#each this.allSitesAllArticles as |a|}} + + Article [{{a.site_id}}] [{{a.article_id}}] + + {{/each}} + {{outlet}} + `); + } + + visitApplication() { + return this.visit('/').then(() => { + var assert = this.assert; + this.links = {}; + this.links['s-1-a-1'] = document.getElementById('s-1-a-1'); + this.links['s-1-a-2'] = document.getElementById('s-1-a-2'); + this.links['s-1-a-3'] = document.getElementById('s-1-a-3'); + this.links['s-2-a-1'] = document.getElementById('s-2-a-1'); + this.links['s-2-a-2'] = document.getElementById('s-2-a-2'); + this.links['s-2-a-3'] = document.getElementById('s-2-a-3'); + this.links['s-3-a-1'] = document.getElementById('s-3-a-1'); + this.links['s-3-a-2'] = document.getElementById('s-3-a-2'); + this.links['s-3-a-3'] = document.getElementById('s-3-a-3'); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.site_controller = this.getController('site'); + this.article_controller = this.getController('site.article'); + }); + } + + async ["@test query params have 'model' stickiness by default"](assert) { + assert.expect(59); + await this.boot(); + this.links['s-1-a-1'].click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-1' + }); + this.assertCurrentPath('/site/s-1/a/a-1'); + await this.setAndFlush(this.article_controller, 'q', 'lol'); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + await this.setAndFlush(this.site_controller, 'country', 'us'); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.links['s-1-a-2'].click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.links['s-2-a-2'].click(); + await (0, _internalTestHelpers.runLoopSettled)(); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?country=us'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?country=us'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + } + + async ["@test query params have 'model' stickiness by default (url changes)"](assert) { + assert.expect(88); + await this.boot(); + this.expectedSiteModelHookParams = { + site_id: 's-1', + country: 'au' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-1', + q: 'lol', + z: 0 + }; + await this.transitionTo('/site/s-1/a/a-1?q=lol'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }, "site controller's model is s-1"); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-1' + }, "article controller's model is a-1"); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.expectedSiteModelHookParams = { + site_id: 's-2', + country: 'us' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-1', + q: 'lol', + z: 0 + }; + await this.transitionTo('/site/s-2/a/a-1?country=us&q=lol'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }, "site controller's model is s-2"); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-1' + }, "article controller's model is a-1"); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.expectedSiteModelHookParams = { + site_id: 's-2', + country: 'us' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-2', + q: 'lol', + z: 0 + }; + await this.transitionTo('/site/s-2/a/a-2?country=us&q=lol'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }, "site controller's model is s-2"); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }, "article controller's model is a-2"); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.expectedSiteModelHookParams = { + site_id: 's-2', + country: 'us' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-3', + q: 'lol', + z: 123 + }; + await this.transitionTo('/site/s-2/a/a-3?country=us&q=lol&z=123'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }, "site controller's model is s-2"); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-3' + }, "article controller's model is a-3"); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 123); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=lol&z=123'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?q=lol&z=123'); + this.expectedSiteModelHookParams = { + site_id: 's-3', + country: 'nz' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-3', + q: 'lol', + z: 123 + }; + await this.transitionTo('/site/s-3/a/a-3?country=nz&q=lol&z=123'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-3' + }, "site controller's model is s-3"); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-3' + }, "article controller's model is a-3"); + assert.equal(this.site_controller.get('country'), 'nz'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 123); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=lol'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=lol&z=123'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=lol'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us&q=lol&z=123'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?country=nz&q=lol'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?country=nz&q=lol'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?country=nz&q=lol&z=123'); + } + + async ["@test query params have 'model' stickiness by default (params-based transitions)"](assert) { + assert.expect(118); + await this.boot(); + this.expectedSiteModelHookParams = { + site_id: 's-1', + country: 'au' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-1', + q: 'wat', + z: 0 + }; + await this.transitionTo('site.article', 's-1', 'a-1'); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-1' + }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'wat'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.expectedSiteModelHookParams = { + site_id: 's-1', + country: 'au' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-2', + q: 'lol', + z: 0 + }; + await this.transitionTo('site.article', 's-1', 'a-2', { + queryParams: { + q: 'lol' + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?q=lol'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3'); + this.expectedSiteModelHookParams = { + site_id: 's-1', + country: 'au' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-3', + q: 'hay', + z: 0 + }; + await this.transitionTo('site.article', 's-1', 'a-3', { + queryParams: { + q: 'hay' + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-3' + }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'hay'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?q=lol'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?q=hay'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?q=hay'); + this.expectedSiteModelHookParams = { + site_id: 's-1', + country: 'au' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-2', + q: 'lol', + z: 1 + }; + await this.transitionTo('site.article', 's-1', 'a-2', { + queryParams: { + z: 1 + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-1' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.site_controller.get('country'), 'au'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 1); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?q=hay'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?q=hay'); + this.expectedSiteModelHookParams = { + site_id: 's-2', + country: 'us' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-2', + q: 'lol', + z: 1 + }; + await this.transitionTo('site.article', 's-2', 'a-2', { + queryParams: { + country: 'us' + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-2' + }); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'lol'); + assert.equal(this.article_controller.get('z'), 1); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us&q=hay'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?q=hay'); + this.expectedSiteModelHookParams = { + site_id: 's-2', + country: 'us' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-1', + q: 'yeah', + z: 0 + }; + await this.transitionTo('site.article', 's-2', 'a-1', { + queryParams: { + q: 'yeah' + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-2' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-1' + }); + assert.equal(this.site_controller.get('country'), 'us'); + assert.equal(this.article_controller.get('q'), 'yeah'); + assert.equal(this.article_controller.get('z'), 0); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=yeah'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=hay'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=yeah'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us&q=hay'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?q=yeah'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?q=hay'); + this.expectedSiteModelHookParams = { + site_id: 's-3', + country: 'nz' + }; + this.expectedArticleModelHookParams = { + article_id: 'a-3', + q: 'hay', + z: 3 + }; + await this.transitionTo('site.article', 's-3', 'a-3', { + queryParams: { + country: 'nz', + z: 3 + } + }); + assert.deepEqual(this.site_controller.get('model'), { + id: 's-3' + }); + assert.deepEqual(this.article_controller.get('model'), { + id: 'a-3' + }); + assert.equal(this.site_controller.get('country'), 'nz'); + assert.equal(this.article_controller.get('q'), 'hay'); + assert.equal(this.article_controller.get('z'), 3); + assert.equal(this.links['s-1-a-1'].getAttribute('href'), '/site/s-1/a/a-1?q=yeah'); + assert.equal(this.links['s-1-a-2'].getAttribute('href'), '/site/s-1/a/a-2?q=lol&z=1'); + assert.equal(this.links['s-1-a-3'].getAttribute('href'), '/site/s-1/a/a-3?q=hay&z=3'); + assert.equal(this.links['s-2-a-1'].getAttribute('href'), '/site/s-2/a/a-1?country=us&q=yeah'); + assert.equal(this.links['s-2-a-2'].getAttribute('href'), '/site/s-2/a/a-2?country=us&q=lol&z=1'); + assert.equal(this.links['s-2-a-3'].getAttribute('href'), '/site/s-2/a/a-3?country=us&q=hay&z=3'); + assert.equal(this.links['s-3-a-1'].getAttribute('href'), '/site/s-3/a/a-1?country=nz&q=yeah'); + assert.equal(this.links['s-3-a-2'].getAttribute('href'), '/site/s-3/a/a-2?country=nz&q=lol&z=1'); + assert.equal(this.links['s-3-a-3'].getAttribute('href'), '/site/s-3/a/a-3?country=nz&q=hay&z=3'); + } + + }); +}); +define("ember/tests/routing/query_params_test/overlapping_query_params_test", ["@ember/controller", "@ember/-internals/routing", "@ember/-internals/metal", "internal-test-helpers"], function (_controller, _routing, _metal, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Query Params - overlapping query param property names', class extends _internalTestHelpers.QueryParamTestCase { + setupBase() { + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + }); + }); + return this.visit('/parent/child'); + } + + async ['@test can remap same-named qp props'](assert) { + assert.expect(7); + this.setMappedQPController('parent'); + this.setMappedQPController('parent.child', 'page', 'childPage'); + await this.setupBase(); + this.assertCurrentPath('/parent/child'); + var parentController = this.getController('parent'); + var parentChildController = this.getController('parent.child'); + await this.setAndFlush(parentController, 'page', 2); + this.assertCurrentPath('/parent/child?parentPage=2'); + await this.setAndFlush(parentController, 'page', 1); + this.assertCurrentPath('/parent/child'); + await this.setAndFlush(parentChildController, 'page', 2); + this.assertCurrentPath('/parent/child?childPage=2'); + await this.setAndFlush(parentChildController, 'page', 1); + this.assertCurrentPath('/parent/child'); + parentController.set('page', 2); + parentChildController.set('page', 2); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/parent/child?childPage=2&parentPage=2'); + parentController.set('page', 1); + parentChildController.set('page', 1); + await (0, _internalTestHelpers.runLoopSettled)(); + this.assertCurrentPath('/parent/child'); + } + + async ['@test query params can be either controller property or url key'](assert) { + assert.expect(3); + this.setMappedQPController('parent'); + await this.setupBase(); + this.assertCurrentPath('/parent/child'); + await this.transitionTo('parent.child', { + queryParams: { + page: 2 + } + }); + this.assertCurrentPath('/parent/child?parentPage=2'); + await this.transitionTo('parent.child', { + queryParams: { + parentPage: 3 + } + }); + this.assertCurrentPath('/parent/child?parentPage=3'); + } + + async ['@test query param matching a url key and controller property'](assert) { + assert.expect(3); + this.setMappedQPController('parent', 'page', 'parentPage'); + this.setMappedQPController('parent.child', 'index', 'page'); + await this.setupBase(); + await this.transitionTo('parent.child', { + queryParams: { + page: 2 + } + }); + this.assertCurrentPath('/parent/child?parentPage=2'); + await this.transitionTo('parent.child', { + queryParams: { + parentPage: 3 + } + }); + this.assertCurrentPath('/parent/child?parentPage=3'); + await this.transitionTo('parent.child', { + queryParams: { + index: 2, + page: 2 + } + }); + this.assertCurrentPath('/parent/child?page=2&parentPage=2'); + } + + async ['@test query param matching same property on two controllers use the urlKey higher in the chain'](assert) { + assert.expect(4); + this.setMappedQPController('parent', 'page', 'parentPage'); + this.setMappedQPController('parent.child', 'page', 'childPage'); + await this.setupBase(); + await this.transitionTo('parent.child', { + queryParams: { + page: 2 + } + }); + this.assertCurrentPath('/parent/child?parentPage=2'); + await this.transitionTo('parent.child', { + queryParams: { + parentPage: 3 + } + }); + this.assertCurrentPath('/parent/child?parentPage=3'); + await this.transitionTo('parent.child', { + queryParams: { + childPage: 2, + page: 2 + } + }); + this.assertCurrentPath('/parent/child?childPage=2&parentPage=2'); + await this.transitionTo('parent.child', { + queryParams: { + childPage: 3, + parentPage: 4 + } + }); + this.assertCurrentPath('/parent/child?childPage=3&parentPage=4'); + } + + async ['@test query params does not error when a query parameter exists for route instances that share a controller'](assert) { + assert.expect(1); + + var parentController = _controller.default.extend({ + queryParams: { + page: 'page' + } + }); + + this.add('controller:parent', parentController); + this.add('route:parent.child', _routing.Route.extend({ + controllerName: 'parent' + })); + await this.setupBase('/parent'); + await this.transitionTo('parent.child', { + queryParams: { + page: 2 + } + }); + this.assertCurrentPath('/parent/child?page=2'); + } + + async ['@test query params in the same route hierarchy with the same url key get auto-scoped'](assert) { + assert.expect(1); + this.setMappedQPController('parent'); + this.setMappedQPController('parent.child'); + await assert.rejectsAssertion(this.setupBase(), "You're not allowed to have more than one controller property map to the same query param key, but both `parent:page` and `parent.child:page` map to `parentPage`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `page: { as: 'other-page' }`"); + } + + async ['@test Support shared but overridable mixin pattern'](assert) { + assert.expect(7); + + var HasPage = _metal.Mixin.create({ + queryParams: 'page', + page: 1 + }); + + this.add('controller:parent', _controller.default.extend(HasPage, { + queryParams: { + page: 'yespage' + } + })); + this.add('controller:parent.child', _controller.default.extend(HasPage)); + await this.setupBase(); + this.assertCurrentPath('/parent/child'); + var parentController = this.getController('parent'); + var parentChildController = this.getController('parent.child'); + await this.setAndFlush(parentChildController, 'page', 2); + this.assertCurrentPath('/parent/child?page=2'); + assert.equal(parentController.get('page'), 1); + assert.equal(parentChildController.get('page'), 2); + await this.setAndFlush(parentController, 'page', 2); + this.assertCurrentPath('/parent/child?page=2&yespage=2'); + assert.equal(parentController.get('page'), 2); + assert.equal(parentChildController.get('page'), 2); + } + + }); +}); +define("ember/tests/routing/query_params_test/query_param_async_get_handler_test", ["@ember/-internals/metal", "@ember/-internals/runtime", "@ember/-internals/routing", "internal-test-helpers"], function (_metal, _runtime, _routing, _internalTestHelpers) { + "use strict"; + + // These tests mimic what happens with lazily loaded Engines. + (0, _internalTestHelpers.moduleFor)('Query Params - async get handler', class extends _internalTestHelpers.QueryParamTestCase { + get routerOptions() { + var fetchedHandlers = this.fetchedHandlers = []; + return { + location: 'test', + + init() { + this._super(...arguments); + + this._seenHandlers = Object.create(null); + this._handlerPromises = Object.create(null); + }, + + setupRouter() { + var isNewSetup = this._super(...arguments); + + if (isNewSetup) { + var { + _handlerPromises: handlerPromises, + _seenHandlers: seenHandlers + } = this; + var getRoute = this._routerMicrolib.getRoute; + + this._routerMicrolib.getRoute = function (routeName) { + fetchedHandlers.push(routeName); // Cache the returns so we don't have more than one Promise for a + // given handler. + + return handlerPromises[routeName] || (handlerPromises[routeName] = new _runtime.RSVP.Promise(resolve => { + setTimeout(() => { + var handler = getRoute(routeName); + seenHandlers[routeName] = handler; + resolve(handler); + }, 10); + })); + }; + } + + return isNewSetup; + }, + + _getQPMeta(routeInfo) { + var handler = this._seenHandlers[routeInfo.name]; + + if (handler) { + return (0, _metal.get)(handler, '_qp'); + } + } + + }; + } + + async ['@test can render a link to an asynchronously loaded route without fetching the route'](assert) { + this.router.map(function () { + this.route('post', { + path: '/post/:id' + }); + }); + this.setSingleQPController('post'); + + var setupAppTemplate = () => { + this.addTemplate('application', ` + Post + Post + {{outlet}} + `); + }; + + setupAppTemplate(); + await this.visitAndAssert('/'); + assert.equal(this.$('.post-link.is-1337').attr('href'), '/post/1337?foo=bar', 'renders correctly with default QP value'); + assert.equal(this.$('.post-link.is-7331').attr('href'), '/post/7331?foo=boo', 'renders correctly with non-default QP value'); + assert.deepEqual(this.fetchedHandlers, ['application', 'index'], `only fetched the handlers for the route we're on`); + } + + ['@test can transitionTo to an asynchronously loaded route with simple query params'](assert) { + assert.expect(6); + this.router.map(function () { + this.route('post', { + path: '/post/:id' + }); + this.route('posts'); + }); + this.setSingleQPController('post'); + var postController; + return this.visitAndAssert('/').then(() => { + postController = this.getController('post'); + return this.transitionTo('posts').then(() => { + this.assertCurrentPath('/posts'); + }); + }).then(() => { + return this.transitionTo('post', 1337, { + queryParams: { + foo: 'boo' + } + }).then(() => { + assert.equal(postController.get('foo'), 'boo', 'simple QP is correctly set on controller'); + this.assertCurrentPath('/post/1337?foo=boo'); + }); + }).then(() => { + return this.transitionTo('post', 1337, { + queryParams: { + foo: 'bar' + } + }).then(() => { + assert.equal(postController.get('foo'), 'bar', 'simple QP is correctly set with default value'); + this.assertCurrentPath('/post/1337'); + }); + }); + } + + ['@test can transitionTo to an asynchronously loaded route with array query params'](assert) { + assert.expect(5); + this.router.map(function () { + this.route('post', { + path: '/post/:id' + }); + }); + this.setSingleQPController('post', 'comments', []); + var postController; + return this.visitAndAssert('/').then(() => { + postController = this.getController('post'); + return this.transitionTo('post', 1337, { + queryParams: { + comments: [1, 2] + } + }).then(() => { + assert.deepEqual(postController.get('comments'), [1, 2], 'array QP is correctly set with default value'); + this.assertCurrentPath('/post/1337?comments=%5B1%2C2%5D'); + }); + }).then(() => { + return this.transitionTo('post', 1338).then(() => { + assert.deepEqual(postController.get('comments'), [], 'array QP is correctly set on controller'); + this.assertCurrentPath('/post/1338'); + }); + }); + } + + ['@test can transitionTo to an asynchronously loaded route with mapped query params'](assert) { + assert.expect(7); + this.router.map(function () { + this.route('post', { + path: '/post/:id' + }, function () { + this.route('index', { + path: '/' + }); + }); + }); + this.setSingleQPController('post'); + this.setMappedQPController('post.index', 'comment', 'note'); + var postController; + var postIndexController; + return this.visitAndAssert('/').then(() => { + postController = this.getController('post'); + postIndexController = this.getController('post.index'); + return this.transitionTo('post.index', 1337, { + queryParams: { + note: 6, + foo: 'boo' + } + }).then(() => { + assert.equal(postController.get('foo'), 'boo', 'simple QP is correctly set on controller'); + assert.equal(postIndexController.get('comment'), 6, 'mapped QP is correctly set on controller'); + this.assertCurrentPath('/post/1337?foo=boo¬e=6'); + }); + }).then(() => { + return this.transitionTo('post', 1337, { + queryParams: { + foo: 'bar' + } + }).then(() => { + assert.equal(postController.get('foo'), 'bar', 'simple QP is correctly set with default value'); + assert.equal(postIndexController.get('comment'), 6, 'mapped QP retains value scoped to model'); + this.assertCurrentPath('/post/1337?note=6'); + }); + }); + } + + ['@test can transitionTo with a URL'](assert) { + assert.expect(7); + this.router.map(function () { + this.route('post', { + path: '/post/:id' + }, function () { + this.route('index', { + path: '/' + }); + }); + }); + this.setSingleQPController('post'); + this.setMappedQPController('post.index', 'comment', 'note'); + var postController; + var postIndexController; + return this.visitAndAssert('/').then(() => { + postController = this.getController('post'); + postIndexController = this.getController('post.index'); + return this.transitionTo('/post/1337?foo=boo¬e=6').then(() => { + assert.equal(postController.get('foo'), 'boo', 'simple QP is correctly deserialized on controller'); + assert.equal(postIndexController.get('comment'), 6, 'mapped QP is correctly deserialized on controller'); + this.assertCurrentPath('/post/1337?foo=boo¬e=6'); + }); + }).then(() => { + return this.transitionTo('/post/1337?note=6').then(() => { + assert.equal(postController.get('foo'), 'bar', 'simple QP is correctly deserialized with default value'); + assert.equal(postIndexController.get('comment'), 6, 'mapped QP retains value scoped to model'); + this.assertCurrentPath('/post/1337?note=6'); + }); + }); + } + + ["@test undefined isn't serialized or deserialized into a string"](assert) { + assert.expect(4); + this.router.map(function () { + this.route('example'); + }); + this.addTemplate('application', "Example"); + this.setSingleQPController('example', 'foo', undefined, { + foo: undefined + }); + this.add('route:example', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + foo: undefined + }); + } + + })); + return this.visitAndAssert('/').then(() => { + assert.equal(this.$('#the-link').attr('href'), '/example', 'renders without undefined qp serialized'); + return this.transitionTo('example', { + queryParams: { + foo: undefined + } + }).then(() => { + this.assertCurrentPath('/example'); + }); + }); + } + + }); +}); +define("ember/tests/routing/query_params_test/query_params_paramless_link_to_test", ["@ember/controller", "internal-test-helpers"], function (_controller, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Query Params - paramless link-to', class extends _internalTestHelpers.QueryParamTestCase { + testParamlessLinks(assert, routeName) { + assert.expect(1); + this.addTemplate(routeName, `index`); + this.add(`controller:${routeName}`, _controller.default.extend({ + queryParams: ['foo'], + foo: 'wat' + })); + return this.visit('/?foo=YEAH').then(() => { + assert.equal(document.getElementById('index-link').getAttribute('href'), '/?foo=YEAH'); + }); + } + + ["@test param-less links in an app booted with query params in the URL don't reset the query params: application"](assert) { + return this.testParamlessLinks(assert, 'application'); + } + + ["@test param-less links in an app booted with query params in the URL don't reset the query params: index"](assert) { + return this.testParamlessLinks(assert, 'index'); + } + + }); +}); +define("ember/tests/routing/query_params_test/shared_state_test", ["@ember/controller", "@ember/service", "@ember/runloop", "internal-test-helpers"], function (_controller, _service, _runloop, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Query Params - shared service state', class extends _internalTestHelpers.QueryParamTestCase { + boot() { + this.setupApplication(); + return this.visitApplication(); + } + + setupApplication() { + this.router.map(function () { + this.route('home', { + path: '/' + }); + this.route('dashboard'); + }); + this.add('service:filters', _service.default.extend({ + shared: true + })); + this.add('controller:home', _controller.default.extend({ + filters: (0, _service.service)() + })); + this.add('controller:dashboard', _controller.default.extend({ + filters: (0, _service.service)(), + queryParams: [{ + 'filters.shared': 'shared' + }] + })); + this.addTemplate('application', `Home
{{outlet}}
`); + this.addTemplate('home', `Dashboard`); + this.addTemplate('dashboard', `Home`); + } + + visitApplication() { + return this.visit('/'); + } + + ['@test can modify shared state before transition'](assert) { + assert.expect(1); + return this.boot().then(() => { + this.$input = document.getElementById('filters-checkbox'); // click the checkbox once to set filters.shared to false + + (0, _runloop.run)(this.$input, 'click'); + return this.visit('/dashboard').then(() => { + assert.ok(true, 'expecting navigating to dashboard to succeed'); + }); + }); + } + + ['@test can modify shared state back to the default value before transition'](assert) { + assert.expect(1); + return this.boot().then(() => { + this.$input = document.getElementById('filters-checkbox'); // click the checkbox twice to set filters.shared to false and back to true + + (0, _runloop.run)(this.$input, 'click'); + (0, _runloop.run)(this.$input, 'click'); + return this.visit('/dashboard').then(() => { + assert.ok(true, 'expecting navigating to dashboard to succeed'); + }); + }); + } + + }); +}); +define("ember/tests/routing/router_map_test", ["internal-test-helpers", "@ember/runloop", "@ember/-internals/routing"], function (_internalTestHelpers, _runloop, _routing) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router.map', class extends _internalTestHelpers.ApplicationTestCase { + ['@test Router.map returns an Ember Router class'](assert) { + assert.expect(1); + var ret = this.router.map(function () { + this.route('hello'); + }); + assert.ok(_routing.Router.detect(ret)); + } + + ['@test Router.map can be called multiple times'](assert) { + assert.expect(2); + this.addTemplate('hello', 'Hello!'); + this.addTemplate('goodbye', 'Goodbye!'); + this.router.map(function () { + this.route('hello'); + }); + this.router.map(function () { + this.route('goodbye'); + }); + return (0, _runloop.run)(() => { + return this.visit('/hello').then(() => { + this.assertText('Hello!'); + }).then(() => { + return this.visit('/goodbye'); + }).then(() => { + this.assertText('Goodbye!'); + }); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/basic_test", ["@ember/-internals/routing", "@ember/-internals/metal", "internal-test-helpers", "@ember/service"], function (_routing, _metal, _internalTestHelpers, _service) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - main', class extends _internalTestHelpers.RouterTestCase { + ['@test RouterService#currentRouteName is correctly set for top level route'](assert) { + assert.expect(6); + return this.visit('/').then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName, + params, + paramNames, + queryParams + } = currentRoute; + assert.equal(name, 'parent.index'); + assert.equal(localName, 'index'); + assert.deepEqual(params, {}); + assert.deepEqual(queryParams, {}); + assert.deepEqual(paramNames, []); + assert.equal(this.routerService.get('currentRouteName'), 'parent.index'); + }); + } + + ['@test RouterService#currentRouteName is correctly set for child route'](assert) { + assert.expect(6); + return this.visit('/child').then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName, + params, + paramNames, + queryParams + } = currentRoute; + assert.equal(name, 'parent.child'); + assert.equal(localName, 'child'); + assert.deepEqual(params, {}); + assert.deepEqual(queryParams, {}); + assert.deepEqual(paramNames, []); + assert.equal(this.routerService.get('currentRouteName'), 'parent.child'); + }); + } + + ['@test RouterService#currentRouteName is correctly set after transition'](assert) { + assert.expect(5); + return this.visit('/child').then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName + } = currentRoute; + assert.equal(name, 'parent.child'); + assert.equal(localName, 'child'); + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName + } = currentRoute; + assert.equal(name, 'parent.sister'); + assert.equal(localName, 'sister'); + assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); + }); + } + + '@test substates survive aborts GH#17430'(assert) { + assert.expect(2); + this.add(`route:parent.child`, _routing.Route.extend({ + beforeModel(transition) { + transition.abort(); + this.intermediateTransitionTo('parent.sister'); + } + + })); + return this.visit('/').then(() => { + return this.routerService.transitionTo('/child'); + }).catch(e => { + assert.equal(this.routerService.currentRouteName, 'parent.sister'); + assert.equal(e.message, 'TransitionAborted'); + }); + } + + ['@test RouterService#currentRouteName is correctly set on each transition'](assert) { + assert.expect(9); + return this.visit('/child').then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName + } = currentRoute; + assert.equal(name, 'parent.child'); + assert.equal(localName, 'child'); + assert.equal(this.routerService.get('currentRouteName'), 'parent.child'); + return this.visit('/sister'); + }).then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName + } = currentRoute; + assert.equal(name, 'parent.sister'); + assert.equal(localName, 'sister'); + assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); + return this.visit('/brother'); + }).then(() => { + var currentRoute = this.routerService.currentRoute; + var { + name, + localName + } = currentRoute; + assert.equal(name, 'parent.brother'); + assert.equal(localName, 'brother'); + assert.equal(this.routerService.get('currentRouteName'), 'parent.brother'); + }); + } + + ['@test RouterService#rootURL is correctly set to the default value'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + assert.equal(this.routerService.get('rootURL'), '/'); + }); + } + + ['@test RouterService#rootURL is correctly set to a custom value'](assert) { + assert.expect(1); + this.add('route:parent.index', _routing.Route.extend({ + init() { + this._super(); + + (0, _metal.set)(this._router, 'rootURL', '/homepage'); + } + + })); + return this.visit('/').then(() => { + assert.equal(this.routerService.get('rootURL'), '/homepage'); + }); + } + + ['@test RouterService#location is correctly delegated from router:main'](assert) { + assert.expect(2); + return this.visit('/').then(() => { + var location = this.routerService.get('location'); + assert.ok(location); + assert.ok(location instanceof _routing.NoneLocation); + }); + } + + ['@test RouterService can be injected into router and accessed on init'](assert) { + assert.expect(1); + this.router.reopen({ + routerService: (0, _service.service)('router'), + + init() { + this.routerService.one('routeDidChange', () => { + assert.ok(true, 'routeDidChange event listener called'); + }); + } + + }); + return this.visit('/'); + } + + }); +}); +define("ember/tests/routing/router_service_test/build_routeinfo_metadata_test", ["internal-test-helpers", "@ember/service", "@ember/-internals/routing"], function (_internalTestHelpers, _service, _routing) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('buildRouteInfoMetadata', class extends _internalTestHelpers.RouterTestCase { + '@test basic metadata'(assert) { + assert.expect(4); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata, 'parent-index-page'); + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata, 'parent-index-page'); + }); + } + + })); + this.add(`route:parent.index`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return 'parent-index-page'; + } + + })); + return this.visit('/'); + } + + '@test hierarchical metadata'(assert) { + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + buildRouteInfoMetadata() { + return 'application-shell'; + }, + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata, 'parent-index-page'); + assert.equal(transition.to.parent.name, 'parent'); + assert.equal(transition.to.parent.metadata, 'parent-page'); + assert.equal(transition.to.parent.parent.name, 'application'); + assert.equal(transition.to.parent.parent.metadata, 'application-shell'); + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata, 'parent-index-page'); + assert.equal(transition.to.parent.name, 'parent'); + assert.equal(transition.to.parent.metadata, 'parent-page'); + assert.equal(transition.to.parent.parent.name, 'application'); + assert.equal(transition.to.parent.parent.metadata, 'application-shell'); + }); + } + + })); + this.add(`route:parent`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return 'parent-page'; + } + + })); + this.add(`route:parent.index`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return 'parent-index-page'; + } + + })); + return this.visit('/'); + } + + '@test metadata can be complex objects'(assert) { + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata.name, 'parent-index-page'); + assert.equal(transition.to.metadata.title('PARENT'), 'My Name is PARENT'); + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.metadata.name, 'parent-index-page'); + assert.equal(transition.to.metadata.title('PARENT'), 'My Name is PARENT'); + }); + } + + })); + this.add(`route:parent`, _routing.Route.extend({})); + this.add(`route:parent.index`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return { + name: 'parent-index-page', + title: name => `My Name is ${name}` + }; + } + + })); + return this.visit('/'); + } + + '@test metadata is placed on the `from`'(assert) { + assert.expect(12); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (transition.to.name === 'parent.index') { + assert.equal(transition.to.metadata.name, 'parent-index-page'); + assert.equal(transition.to.metadata.title('INDEX'), 'My Name is INDEX'); + } else { + assert.equal(transition.from.metadata.name, 'parent-index-page'); + assert.equal(transition.from.metadata.title('INDEX'), 'My Name is INDEX'); + assert.equal(transition.to.metadata.name, 'parent-child-page'); + assert.equal(transition.to.metadata.title('CHILD'), 'My Name is CHILD!!'); + } + }); + this.router.on('routeDidChange', transition => { + if (transition.to.name === 'parent.index') { + assert.equal(transition.to.metadata.name, 'parent-index-page'); + assert.equal(transition.to.metadata.title('INDEX'), 'My Name is INDEX'); + } else { + assert.equal(transition.from.metadata.name, 'parent-index-page'); + assert.equal(transition.from.metadata.title('INDEX'), 'My Name is INDEX'); + assert.equal(transition.to.metadata.name, 'parent-child-page'); + assert.equal(transition.to.metadata.title('CHILD'), 'My Name is CHILD!!'); + } + }); + } + + })); + this.add(`route:parent`, _routing.Route.extend({})); + this.add(`route:parent.index`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return { + name: 'parent-index-page', + title: name => `My Name is ${name}` + }; + } + + })); + this.add(`route:parent.child`, _routing.Route.extend({ + buildRouteInfoMetadata() { + return { + name: 'parent-child-page', + title: name => `My Name is ${name}!!` + }; + } + + })); + return this.visit('/').then(() => { + return this.visit('/child'); + }); + } + + '@test can be used with model data from `attributes`'(assert) { + assert.expect(6); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeDidChange', transition => { + if (transition.to.name === 'parent.index') { + assert.equal(transition.to.metadata.name, 'parent-index-page'); + assert.equal(transition.to.metadata.title(transition.to.attributes), 'My Name is INDEX'); + } else { + assert.equal(transition.from.metadata.name, 'parent-index-page'); + assert.equal(transition.from.metadata.title(transition.from.attributes), 'My Name is INDEX'); + assert.equal(transition.to.metadata.name, 'parent-child-page'); + assert.equal(transition.to.metadata.title(transition.to.attributes), 'My Name is CHILD!!'); + } + }); + } + + })); + this.add(`route:parent`, _routing.Route.extend({})); + this.add(`route:parent.index`, _routing.Route.extend({ + model() { + return { + name: 'INDEX' + }; + }, + + buildRouteInfoMetadata() { + return { + name: 'parent-index-page', + title: model => `My Name is ${model.name}` + }; + } + + })); + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + return { + name: 'CHILD' + }; + }, + + buildRouteInfoMetadata() { + return { + name: 'parent-child-page', + title: model => `My Name is ${model.name}!!` + }; + } + + })); + return this.visit('/').then(() => { + return this.visit('/child'); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/currenturl_lifecycle_test", ["@ember/service", "@ember/object/computed", "@ember/-internals/glimmer", "@ember/-internals/routing", "@ember/-internals/metal", "internal-test-helpers", "@ember/-internals/runtime"], function (_service, _computed, _glimmer, _routing, _metal, _internalTestHelpers, _runtime) { + "use strict"; + + var results = []; + var ROUTE_NAMES = ['index', 'child', 'sister', 'brother', 'loading']; + + var InstrumentedRoute = _routing.Route.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + var service = (0, _metal.get)(this, 'routerService'); + service.on('routeWillChange', transition => { + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} routeWillChange: ${transition.from && transition.from.name} - ${transition.to.name}`, service.get('currentURL')]); + }); + service.on('routeDidChange', transition => { + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} routeDidChange: ${transition.from && transition.from.name} - ${transition.to.name}`, service.get('currentURL')]); + }); + }, + + activate() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} activate`, service.get('currentURL')]); + }, + + redirect() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} redirect`, service.get('currentURL')]); + }, + + beforeModel() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} beforeModel`, service.get('currentURL')]); + }, + + model() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} model`, service.get('currentURL')]); + return new _runtime.RSVP.Promise(resolve => { + setTimeout(resolve, 200); + }); + }, + + afterModel() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} afterModel`, service.get('currentURL')]); + }, + + actions: { + willTransition(transition) { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} willTransition: ${transition.from && transition.from.name} - ${transition.to.name}`, service.get('currentURL')]); + return true; + }, + + didTransition() { + var service = (0, _metal.get)(this, 'routerService'); + results.push([`${service.get('currentRouteName')} - ${service.get('currentRoute.name')}`, `${this.routeName} didTransition`, service.get('currentURL')]); + return true; + } + + } + }); + + (0, _internalTestHelpers.moduleFor)('Router Service - currentURL | currentRouteName | currentRoute.name', class extends _internalTestHelpers.RouterTestCase { + constructor() { + super(...arguments); + results = []; + ROUTE_NAMES.forEach(name => { + var routeName = `parent.${name}`; + this.add(`route:${routeName}`, InstrumentedRoute.extend()); + this.addTemplate(routeName, '{{current-url}}'); + }); + + var CurrenURLComponent = _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + currentURL: (0, _computed.readOnly)('routerService.currentURL'), + currentRouteName: (0, _computed.readOnly)('routerService.currentRouteName'), + currentRoute: (0, _computed.readOnly)('routerService.currentRoute') + }); + + this.addComponent('current-url', { + ComponentClass: CurrenURLComponent, + template: '{{this.currentURL}}-{{this.currentRouteName}}-{{this.currentRoute.name}}' + }); + } + + ['@test RouterService#currentURL is correctly set for top level route'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + assert.equal(this.routerService.get('currentURL'), '/'); + }); + } + + ['@test RouterService#currentURL is correctly set for child route'](assert) { + assert.expect(1); + return this.visit('/child').then(() => { + assert.equal(this.routerService.get('currentURL'), '/child'); + }); + } + + ['@test RouterService#currentURL is correctly set after transition'](assert) { + assert.expect(1); + return this.visit('/child').then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/sister'); + }); + } + + ['@test RouterService#currentURL is correctly set on each transition'](assert) { + assert.expect(3); + return this.visit('/child').then(() => { + assert.equal(this.routerService.get('currentURL'), '/child'); + return this.visit('/sister'); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/sister'); + return this.visit('/brother'); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/brother'); + }); + } + + ['@test RouterService#currentURL is not set during model lifecycle hooks until routeDidChange'](assert) { + assert.expect(2); + return this.visit('/').then(() => { + assert.deepEqual(results, [['null - undefined', 'parent.index routeWillChange: null - parent.index', null], ['null - undefined', 'parent.index beforeModel', null], ['null - undefined', 'parent.index model', null], ['null - undefined', 'parent.loading activate', null], ['null - undefined', 'parent.loading routeWillChange: null - parent.loading', null], ['null - undefined', 'parent.index routeWillChange: null - parent.loading', null], ['parent.loading - parent.loading', 'parent.index afterModel', '/'], ['parent.loading - parent.loading', 'parent.index redirect', '/'], ['parent.loading - parent.loading', 'parent.index activate', '/'], ['parent.loading - parent.loading', 'parent.index didTransition', '/'], ['parent.index - parent.index', 'parent.loading routeDidChange: null - parent.index', '/'], ['parent.index - parent.index', 'parent.index routeDidChange: null - parent.index', '/']]); + results = []; + return this.visit('/child'); + }).then(() => { + assert.deepEqual(results, [['parent.index - parent.index', 'parent.index willTransition: parent.index - parent.child', '/'], ['parent.index - parent.index', 'parent.child routeWillChange: parent.index - parent.child', '/'], ['parent.index - parent.index', 'parent.loading routeWillChange: parent.index - parent.child', '/'], ['parent.index - parent.index', 'parent.index routeWillChange: parent.index - parent.child', '/'], ['parent.index - parent.index', 'parent.child beforeModel', '/'], ['parent.index - parent.index', 'parent.child model', '/'], ['parent.index - parent.index', 'parent.loading activate', '/'], ['parent.index - parent.index', 'parent.child routeWillChange: parent.index - parent.loading', '/'], ['parent.index - parent.index', 'parent.loading routeWillChange: parent.index - parent.loading', '/'], ['parent.index - parent.index', 'parent.index routeWillChange: parent.index - parent.loading', '/'], ['parent.loading - parent.loading', 'parent.child afterModel', '/child'], ['parent.loading - parent.loading', 'parent.child redirect', '/child'], ['parent.loading - parent.loading', 'parent.child activate', '/child'], ['parent.loading - parent.loading', 'parent.child didTransition', '/child'], ['parent.child - parent.child', 'parent.child routeDidChange: parent.index - parent.child', '/child'], ['parent.child - parent.child', 'parent.loading routeDidChange: parent.index - parent.child', '/child'], ['parent.child - parent.child', 'parent.index routeDidChange: parent.index - parent.child', '/child']]); + }); + } + + ['@test RouterService#currentURL is correctly set with component after consecutive visits'](assert) { + assert.expect(3); + return this.visit('/').then(() => { + this.assertText('/-parent.index-parent.index'); + return this.visit('/child'); + }).then(() => { + this.assertText('/child-parent.child-parent.child'); + return this.visit('/'); + }).then(() => { + this.assertText('/-parent.index-parent.index'); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/events_test", ["internal-test-helpers", "@ember/service", "@ember/-internals/routing", "@ember/runloop"], function (_internalTestHelpers, _service, _routing, _runloop) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - events', class extends _internalTestHelpers.RouterTestCase { + '@test initial render'(assert) { + assert.expect(12); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.ok(transition); + assert.equal(transition.from, undefined); + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.localName, 'index'); + }); + this.router.on('routeDidChange', transition => { + assert.ok(transition); + assert.ok(this.router.currentURL, `has URL ${this.router.currentURL}`); + assert.equal(this.router.currentURL, '/'); + assert.ok(this.router.currentRouteName, `has route name ${this.router.currentRouteName}`); + assert.equal(this.router.currentRouteName, 'parent.index'); + assert.equal(transition.from, undefined); + assert.equal(transition.to.name, 'parent.index'); + assert.equal(transition.to.localName, 'index'); + }); + } + + })); + return this.visit('/'); + } + + '@test subsequent visits'(assert) { + assert.expect(24); + var toParent = true; + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (toParent) { + assert.equal(this.router.currentURL, null, 'starts as null'); + assert.equal(transition.from, undefined); + assert.equal(transition.to.name, 'parent.child'); + assert.equal(transition.to.localName, 'child'); + assert.equal(transition.to.parent.name, 'parent', 'parent node'); + assert.equal(transition.to.parent.child, transition.to, 'parents child node is the `to`'); + assert.equal(transition.to.parent.parent.name, 'application', 'top level'); + assert.equal(transition.to.parent.parent.parent, null, 'top level'); + } else { + assert.equal(this.router.currentURL, '/child', 'not changed until transition'); + assert.notEqual(transition.from, undefined); + assert.equal(transition.from.name, 'parent.child'); + assert.equal(transition.from.localName, 'child'); + assert.equal(transition.to.localName, 'sister'); + assert.equal(transition.to.name, 'parent.sister'); + } + }); + this.router.on('routeDidChange', transition => { + if (toParent) { + assert.equal(this.router.currentURL, '/child'); + assert.equal(transition.from, undefined); + assert.equal(transition.to.name, 'parent.child'); + assert.equal(transition.to.localName, 'child'); + } else { + assert.equal(this.router.currentURL, '/sister'); + assert.notEqual(transition.from, undefined); + assert.equal(transition.from.name, 'parent.child'); + assert.equal(transition.from.localName, 'child'); + assert.equal(transition.to.localName, 'sister'); + assert.equal(transition.to.name, 'parent.sister'); + } + }); + } + + })); + return this.visit('/child').then(() => { + toParent = false; + return this.routerService.transitionTo('parent.sister'); + }); + } + + '@test transitions can be retried async'(assert) { + var done = assert.async(); + this.add(`route:parent.child`, _routing.Route.extend({ + actions: { + willTransition(transition) { + transition.abort(); + this.intermediateTransitionTo('parent.sister'); + (0, _runloop.later)(() => { + transition.retry(); + done(); + }, 500); + } + + } + })); + return this.visit('/child').then(() => { + return this.visit('/'); + }).catch(e => { + assert.equal(e.message, 'TransitionAborted'); + }); + } + + '@test redirection with `transitionTo`'(assert) { + assert.expect(11); + var toChild = false; + var toSister = false; + this.add(`route:parent`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.transitionTo('parent.child'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.transitionTo('parent.sister'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.from, undefined, 'initial'); + + if (toChild) { + if (toSister) { + assert.equal(transition.to.name, 'parent.sister', 'going to /sister'); + } else { + assert.equal(transition.to.name, 'parent.child', 'going to /child'); + toSister = true; + } + } else { + // Going to `/` + assert.equal(transition.to.name, 'parent.index', 'going to /'); + toChild = true; + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.from, undefined, 'initial'); + assert.equal(transition.to.name, 'parent.sister', 'landed on /sister'); + }); + } + + })); + return this.visit('/'); + } + + '@test redirection with `replaceWith`'(assert) { + assert.expect(11); + var toChild = false; + var toSister = false; + this.add(`route:parent`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.replaceWith('parent.child'); + }, /Calling replaceWith on a route is deprecated/); + } + + })); + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.replaceWith('parent.sister'); + }, /Calling replaceWith on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.from, undefined, 'initial'); + + if (toChild) { + if (toSister) { + assert.equal(transition.to.name, 'parent.sister', 'going to /sister'); + } else { + assert.equal(transition.to.name, 'parent.child', 'going to /child'); + toSister = true; + } + } else { + // Going to `/` + assert.equal(transition.to.name, 'parent.index', 'going to /'); + toChild = true; + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.from, undefined, 'initial'); + assert.equal(transition.to.name, 'parent.sister', 'landed on /sister'); + }); + } + + })); + return this.visit('/'); + } + + '@test nested redirection with `transitionTo`'(assert) { + assert.expect(12); + var toChild = false; + var toSister = false; + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.transitionTo('parent.sister'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (toChild) { + assert.equal(transition.from.name, 'parent.index'); + + if (toSister) { + assert.equal(transition.to.name, 'parent.sister', 'going to /sister'); + } else { + assert.equal(transition.to.name, 'parent.child', 'going to /child'); + toSister = true; + } + } else { + // Going to `/` + assert.equal(transition.to.name, 'parent.index', 'going to /'); + assert.equal(transition.from, undefined, 'initial'); + } + }); + this.router.on('routeDidChange', transition => { + if (toSister) { + assert.equal(transition.from.name, 'parent.index', 'initial'); + assert.equal(transition.to.name, 'parent.sister', 'landed on /sister'); + } else { + assert.equal(transition.from, undefined, 'initial'); + assert.equal(transition.to.name, 'parent.index', 'landed on /'); + } + }); + } + + })); + return this.visit('/').then(() => { + toChild = true; + return this.routerService.transitionTo('/child').catch(e => { + assert.equal(e.name, 'TransitionAborted', 'Transition aborted'); + }); + }); + } + + '@test nested redirection with `replaceWith`'(assert) { + assert.expect(12); + var toChild = false; + var toSister = false; + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + expectDeprecation(() => { + this.replaceWith('parent.sister'); + }, /Calling replaceWith on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (toChild) { + assert.equal(transition.from.name, 'parent.index'); + + if (toSister) { + assert.equal(transition.to.name, 'parent.sister', 'going to /sister'); + } else { + assert.equal(transition.to.name, 'parent.child', 'going to /child'); + toSister = true; + } + } else { + // Going to `/` + assert.equal(transition.to.name, 'parent.index', 'going to /'); + assert.equal(transition.from, undefined, 'initial'); + } + }); + this.router.on('routeDidChange', transition => { + if (toSister) { + assert.equal(transition.from.name, 'parent.index', 'initial'); + assert.equal(transition.to.name, 'parent.sister', 'landed on /sister'); + } else { + assert.equal(transition.from, undefined, 'initial'); + assert.equal(transition.to.name, 'parent.index', 'landed on /'); + } + }); + } + + })); + return this.visit('/').then(() => { + toChild = true; + return this.routerService.transitionTo('/child').catch(e => { + assert.equal(e.name, 'TransitionAborted', 'Transition aborted'); + }); + }); + } + + '@test aborted transition'(assert) { + assert.expect(11); + var didAbort = false; + var toChild = false; + this.add(`route:parent.child`, _routing.Route.extend({ + model(_model, transition) { + didAbort = true; + transition.abort(); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (didAbort) { + assert.equal(transition.to.name, 'parent.index', 'transition aborted'); + assert.equal(transition.from.name, 'parent.index', 'transition aborted'); + } else if (toChild) { + assert.equal(transition.from.name, 'parent.index', 'from /'); + assert.equal(transition.to.name, 'parent.child', 'to /child'); + } else { + assert.equal(transition.to.name, 'parent.index', 'going to /'); + assert.equal(transition.from, undefined, 'initial'); + } + }); + this.router.on('routeDidChange', transition => { + if (didAbort) { + assert.equal(transition.to.name, 'parent.index', 'landed on /'); + assert.equal(transition.from.name, 'parent.index', 'initial'); + } else { + assert.equal(transition.to.name, 'parent.index', 'transition aborted'); + assert.equal(transition.from, undefined, 'transition aborted'); + } + }); + } + + })); + return this.visit('/').then(() => { + toChild = true; + return this.routerService.transitionTo('/child').catch(e => { + assert.equal(e.name, 'TransitionAborted', 'Transition aborted'); + }); + }); + } + + '@test query param transitions'(assert) { + assert.expect(15); + var initial = true; + var addQP = false; + var removeQP = false; + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'parent.index'); + + if (initial) { + assert.equal(transition.from, null); + assert.deepEqual(transition.to.queryParams, { + a: 'true' + }); + } else if (addQP) { + assert.deepEqual(transition.from.queryParams, { + a: 'true' + }); + assert.deepEqual(transition.to.queryParams, { + a: 'false', + b: 'b' + }); + } else if (removeQP) { + assert.deepEqual(transition.from.queryParams, { + a: 'false', + b: 'b' + }); + assert.deepEqual(transition.to.queryParams, { + a: 'false' + }); + } else { + assert.ok(false, 'never'); + } + }); + this.router.on('routeDidChange', transition => { + if (initial) { + assert.equal(transition.from, null); + assert.deepEqual(transition.to.queryParams, { + a: 'true' + }); + } else if (addQP) { + assert.deepEqual(transition.from.queryParams, { + a: 'true' + }); + assert.deepEqual(transition.to.queryParams, { + a: 'false', + b: 'b' + }); + } else if (removeQP) { + assert.deepEqual(transition.from.queryParams, { + a: 'false', + b: 'b' + }); + assert.deepEqual(transition.to.queryParams, { + a: 'false' + }); + } else { + assert.ok(false, 'never'); + } + }); + } + + })); + return this.visit('/?a=true').then(() => { + addQP = true; + initial = false; + return this.routerService.transitionTo('/?a=false&b=b'); + }).then(() => { + removeQP = true; + addQP = false; + return this.routerService.transitionTo('/?a=false'); + }); + } + + '@test query param redirects with `transitionTo`'(assert) { + assert.expect(7); + var toSister = false; + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + toSister = true; + expectDeprecation(() => { + this.transitionTo('/sister?a=a'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (toSister) { + assert.equal(transition.to.name, 'parent.sister'); + assert.deepEqual(transition.to.queryParams, { + a: 'a' + }); + } else { + assert.equal(transition.to.name, 'parent.child'); + assert.deepEqual(transition.to.queryParams, {}); + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'parent.sister'); + assert.deepEqual(transition.to.queryParams, { + a: 'a' + }); + }); + } + + })); + return this.visit('/child'); + } + + '@test query param redirects with `replaceWith`'(assert) { + assert.expect(7); + var toSister = false; + this.add(`route:parent.child`, _routing.Route.extend({ + model() { + toSister = true; + expectDeprecation(() => { + this.replaceWith('/sister?a=a'); + }, /Calling replaceWith on a route is deprecated/); + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + if (toSister) { + assert.equal(transition.to.name, 'parent.sister'); + assert.deepEqual(transition.to.queryParams, { + a: 'a' + }); + } else { + assert.equal(transition.to.name, 'parent.child'); + assert.deepEqual(transition.to.queryParams, {}); + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'parent.sister'); + assert.deepEqual(transition.to.queryParams, { + a: 'a' + }); + }); + } + + })); + return this.visit('/child'); + } + + '@test params'(assert) { + assert.expect(14); + var initial = true; + this.add('route:dynamic', _routing.Route.extend({ + model(params) { + if (initial) { + assert.deepEqual(params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(params, { + dynamic_id: '1' + }); + } + + return params; + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'dynamic'); + + if (initial) { + assert.deepEqual(transition.to.paramNames, ['dynamic_id']); + assert.deepEqual(transition.to.params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(transition.to.paramNames, ['dynamic_id']); + assert.deepEqual(transition.to.params, { + dynamic_id: '1' + }); + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'dynamic'); + assert.deepEqual(transition.to.paramNames, ['dynamic_id']); + + if (initial) { + assert.deepEqual(transition.to.params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(transition.to.params, { + dynamic_id: '1' + }); + } + }); + } + + })); + return this.visit('/dynamic/123').then(() => { + initial = false; + return this.routerService.transitionTo('dynamic', 1); + }); + } + + '@test nested params'(assert) { + assert.expect(30); + var initial = true; + this.add('route:dynamicWithChild', _routing.Route.extend({ + model(params) { + if (initial) { + assert.deepEqual(params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(params, { + dynamic_id: '456' + }); + } + + return params.dynamic_id; + } + + })); + this.add('route:dynamicWithChild.child', _routing.Route.extend({ + model(params) { + assert.deepEqual(params, { + child_id: '456' + }); + return params.child_id; + } + + })); + this.add(`route:application`, _routing.Route.extend({ + router: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + this.router.on('routeWillChange', transition => { + assert.equal(transition.to.name, 'dynamicWithChild.child'); + assert.deepEqual(transition.to.paramNames, ['child_id']); + assert.deepEqual(transition.to.params, { + child_id: '456' + }); + assert.deepEqual(transition.to.parent.paramNames, ['dynamic_id']); + + if (initial) { + assert.deepEqual(transition.to.parent.params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(transition.from.attributes, '456'); + assert.deepEqual(transition.from.parent.attributes, '123'); + assert.deepEqual(transition.to.parent.params, { + dynamic_id: '456' + }); + } + }); + this.router.on('routeDidChange', transition => { + assert.equal(transition.to.name, 'dynamicWithChild.child'); + assert.deepEqual(transition.to.paramNames, ['child_id']); + assert.deepEqual(transition.to.params, { + child_id: '456' + }); + assert.deepEqual(transition.to.parent.paramNames, ['dynamic_id']); + + if (initial) { + assert.deepEqual(transition.to.parent.params, { + dynamic_id: '123' + }); + } else { + assert.deepEqual(transition.from.attributes, '456'); + assert.deepEqual(transition.from.parent.attributes, '123'); + assert.deepEqual(transition.to.attributes, '456'); + assert.deepEqual(transition.to.parent.attributes, '456'); + assert.deepEqual(transition.to.parent.params, { + dynamic_id: '456' + }); + } + }); + } + + })); + return this.visit('/dynamic-with-child/123/456').then(() => { + initial = false; + return this.routerService.transitionTo('/dynamic-with-child/456/456'); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/isActive_test", ["@ember/controller", "internal-test-helpers", "@ember/service"], function (_controller, _internalTestHelpers, _service) { + "use strict"; + + function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); + } + + function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object.keys(descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + + return desc; + } + + function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and runs after the decorators transform.'); + } + + (0, _internalTestHelpers.moduleFor)('Router Service - isActive', class extends _internalTestHelpers.RouterTestCase { + ['@test RouterService#isActive returns true for simple route'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + assert.ok(this.routerService.isActive('parent.sister')); + }); + } + + ['@test RouterService#isActive returns true for simple route with dynamic segments'](assert) { + assert.expect(1); + var dynamicModel = { + id: 1 + }; + return this.visit('/').then(() => { + return this.routerService.transitionTo('dynamic', dynamicModel); + }).then(() => { + assert.ok(this.routerService.isActive('dynamic', dynamicModel)); + }); + } + + async ['@test RouterService#isActive entangles with route transitions'](assert) { + var _class, _descriptor; + + assert.expect(6); + this.add(`service:foo`, (_class = class _class extends _service.default { + constructor(...args) { + super(...args); + + _initializerDefineProperty(this, "router", _descriptor, this); + } + + get isChildActive() { + return this.router.isActive('parent.child'); + } + + get isSisterActive() { + return this.router.isActive('parent.sister'); + } + + }, _descriptor = _applyDecoratedDescriptor(_class.prototype, "router", [_service.service], { + configurable: true, + enumerable: true, + writable: true, + initializer: null + }), _class)); + await this.visit('/'); + var fooService = this.applicationInstance.lookup('service:foo'); + assert.equal(fooService.isChildActive, false); + assert.equal(fooService.isSisterActive, false); + await this.routerService.transitionTo('parent.child'); + assert.equal(fooService.isChildActive, true); + assert.equal(fooService.isSisterActive, false); + await this.routerService.transitionTo('parent.sister'); + assert.equal(fooService.isChildActive, false); + assert.equal(fooService.isSisterActive, true); + } + + ['@test RouterService#isActive does not eagerly instantiate controller for query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + this.add('controller:parent.sister', _controller.default.extend({ + queryParams: ['sort'], + sort: 'ASC', + + init() { + assert.ok(false, 'should never create'); + + this._super(...arguments); + } + + })); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.brother'); + }).then(() => { + assert.notOk(this.routerService.isActive('parent.sister', queryParams)); + }); + } + + ['@test RouterService#isActive is correct for simple route with basic query params'](assert) { + assert.expect(2); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort'], + sort: 'ASC' + })); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }).then(() => { + assert.ok(this.routerService.isActive('parent.child', queryParams)); + assert.notOk(this.routerService.isActive('parent.child', this.buildQueryParams({ + sort: 'DESC' + }))); + }); + } + + ['@test RouterService#isActive for simple route with array as query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + sort: ['ascending'] + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }).then(() => { + assert.notOk(this.routerService.isActive('parent.child', this.buildQueryParams({ + sort: 'descending' + }))); + }); + } + + ['@test RouterService#isActive does not alter query params hash'](assert) { + assert.expect(3); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort', 'page'], + sort: 'ASC', + page: 1 + })); + var qp = this.buildQueryParams({ + sort: 'ascending' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', qp); + }).then(() => { + assert.ok(this.routerService.isActive('parent.child', qp)); + assert.ok(this.routerService.isActive('parent.child', qp)); // using same qp second time should not fail + + assert.deepEqual(qp.queryParams, { + sort: 'ascending' + }); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/non_application_test_test", ["@ember/service", "@ember/-internals/routing", "@ember/-internals/metal", "@ember/runloop", "@ember/-internals/glimmer", "internal-test-helpers"], function (_service, _routing, _metal, _runloop, _glimmer, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - non application test', class extends _internalTestHelpers.RouterNonApplicationTestCase { + constructor() { + super(...arguments); + this.resolver.add('router:main', _routing.Router.extend(this.routerOptions)); + this.router.map(function () { + this.route('parent', { + path: '/' + }, function () { + this.route('child'); + this.route('sister'); + this.route('brother'); + }); + this.route('dynamic', { + path: '/dynamic/:dynamic_id' + }); + this.route('dynamicWithChild', { + path: '/dynamic-with-child/:dynamic_id' + }, function () { + this.route('child', { + path: '/:child_id' + }); + }); + }); + } + + get routerOptions() { + return { + location: 'none' + }; + } + + get router() { + return this.owner.resolveRegistration('router:main'); + } + + get routerService() { + return this.owner.lookup('service:router'); + } + + ['@test RouterService can be instantiated in non application test'](assert) { + assert.ok(this.routerService); + } + + ['@test RouterService properties can be accessed with default'](assert) { + assert.expect(5); + assert.equal(this.routerService.get('currentRouteName'), null); + assert.equal(this.routerService.get('currentURL'), null); + assert.equal(this.routerService.get('location'), 'none'); + assert.equal(this.routerService.get('rootURL'), '/'); + assert.equal(this.routerService.get('currentRoute'), null); + } + + ['@test RouterService properties of router can be accessed with default when router is present'](assert) { + assert.expect(5); + var router = this.owner.lookup('router:main'); + router.setupRouter(); + assert.equal(this.routerService.get('currentRouteName'), null); + assert.equal(this.routerService.get('currentURL'), null); + assert.ok(this.routerService.get('location') instanceof _routing.NoneLocation); + assert.equal(this.routerService.get('rootURL'), '/'); + assert.equal(this.routerService.get('currentRoute'), null); + } + + ['@test RouterService#urlFor returns url'](assert) { + assert.equal(this.routerService.urlFor('parent.child'), '/child'); + } + + ['@test RouterService#transitionTo with basic route'](assert) { + assert.expect(2); // Callers who want to actually execute a transition in a non-application + // test are doing something weird and therefore should do + // `owner.setupRouter()` explicitly in their tests. + + var componentInstance; + var router = this.owner.lookup('router:main'); + router.setupRouter(); + this.addTemplate('parent.index', '{{foo-bar}}'); + this.addComponent('foo-bar', { + ComponentClass: _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(...arguments); + + componentInstance = this; + }, + + actions: { + transitionToSister() { + (0, _metal.get)(this, 'routerService').transitionTo('parent.sister'); + } + + } + }), + template: `foo-bar` + }); + this.render('{{foo-bar}}'); + (0, _runloop.run)(function () { + componentInstance.send('transitionToSister'); + }); + assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); + assert.ok(this.routerService.isActive('parent.sister')); + } + + ['@test RouterService#recognize recognize returns routeInfo'](assert) { + var routeInfo = this.routerService.recognize('/dynamic-with-child/123/1?a=b'); + assert.ok(routeInfo); + var { + name, + localName, + parent, + child, + params, + queryParams, + paramNames + } = routeInfo; + assert.equal(name, 'dynamicWithChild.child'); + assert.equal(localName, 'child'); + assert.ok(parent); + assert.equal(parent.name, 'dynamicWithChild'); + assert.notOk(child); + assert.deepEqual(params, { + child_id: '1' + }); + assert.deepEqual(queryParams, { + a: 'b' + }); + assert.deepEqual(paramNames, ['child_id']); + } + + }); +}); +define("ember/tests/routing/router_service_test/recognize_test", ["internal-test-helpers", "@ember/-internals/routing"], function (_internalTestHelpers, _routing) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - recognize', class extends _internalTestHelpers.RouterTestCase { + '@test returns a RouteInfo for recognized URL'(assert) { + return this.visit('/').then(() => { + var routeInfo = this.routerService.recognize('/dynamic-with-child/123/1?a=b'); + assert.ok(routeInfo); + var { + name, + localName, + parent, + child, + params, + queryParams, + paramNames + } = routeInfo; + assert.equal(name, 'dynamicWithChild.child'); + assert.equal(localName, 'child'); + assert.ok(parent); + assert.equal(parent.name, 'dynamicWithChild'); + assert.notOk(child); + assert.deepEqual(params, { + child_id: '1' + }); + assert.deepEqual(queryParams, { + a: 'b' + }); + assert.deepEqual(paramNames, ['child_id']); + }); + } + + '@test does not transition'(assert) { + this.addTemplate('parent', 'Parent'); + this.addTemplate('dynamic-with-child.child', 'Dynamic Child'); + return this.visit('/').then(() => { + this.routerService.recognize('/dynamic-with-child/123/1?a=b'); + this.assertText('Parent', 'Did not transition and cause render'); + assert.equal(this.routerService.currentURL, '/', 'Did not transition'); + }); + } + + '@test respects the usage of a different rootURL'(assert) { + this.router.reopen({ + rootURL: '/app/' + }); + return this.visit('/app').then(() => { + var routeInfo = this.routerService.recognize('/app/child/'); + assert.ok(routeInfo); + var { + name, + localName, + parent + } = routeInfo; + assert.equal(name, 'parent.child'); + assert.equal(localName, 'child'); + assert.equal(parent.name, 'parent'); + }); + } + + '@test must include rootURL'() { + this.addTemplate('parent', 'Parent'); + this.addTemplate('dynamic-with-child.child', 'Dynamic Child'); + this.router.reopen({ + rootURL: '/app/' + }); + return this.visit('/app').then(() => { + expectAssertion(() => { + this.routerService.recognize('/dynamic-with-child/123/1?a=b'); + }, 'You must pass a url that begins with the application\'s rootURL "/app/"'); + }); + } + + '@test returns `null` if URL is not recognized'(assert) { + return this.visit('/').then(() => { + var routeInfo = this.routerService.recognize('/foo'); + assert.equal(routeInfo, null); + }); + } + + }); + (0, _internalTestHelpers.moduleFor)('Router Service - recognizeAndLoad', class extends _internalTestHelpers.RouterTestCase { + '@test returns a RouteInfoWithAttributes for recognized URL'(assert) { + this.add('route:dynamicWithChild', _routing.Route.extend({ + model(params) { + return { + name: 'dynamicWithChild', + data: params.dynamic_id + }; + } + + })); + this.add('route:dynamicWithChild.child', _routing.Route.extend({ + model(params) { + return { + name: 'dynamicWithChild.child', + data: params.child_id + }; + } + + })); + return this.visit('/').then(() => { + return this.routerService.recognizeAndLoad('/dynamic-with-child/123/1?a=b'); + }).then(routeInfoWithAttributes => { + assert.ok(routeInfoWithAttributes); + var { + name, + localName, + parent, + attributes, + paramNames, + params, + queryParams + } = routeInfoWithAttributes; + assert.equal(name, 'dynamicWithChild.child'); + assert.equal(localName, 'child'); + assert.equal(parent.name, 'dynamicWithChild'); + assert.deepEqual(params, { + child_id: '1' + }); + assert.deepEqual(queryParams, { + a: 'b' + }); + assert.deepEqual(paramNames, ['child_id']); + assert.deepEqual(attributes, { + name: 'dynamicWithChild.child', + data: '1' + }); + assert.deepEqual(parent.attributes, { + name: 'dynamicWithChild', + data: '123' + }); + assert.deepEqual(parent.paramNames, ['dynamic_id']); + assert.deepEqual(parent.params, { + dynamic_id: '123' + }); + }); + } + + '@test does not transition'(assert) { + this.addTemplate('parent', 'Parent{{outlet}}'); + this.addTemplate('parent.child', 'Child'); + this.add('route:parent.child', _routing.Route.extend({ + model() { + return { + name: 'child', + data: ['stuff'] + }; + } + + })); + return this.visit('/').then(() => { + this.routerService.on('routeWillChange', () => assert.ok(false)); + this.routerService.on('routeDidChange', () => assert.ok(false)); + return this.routerService.recognizeAndLoad('/child'); + }).then(() => { + assert.equal(this.routerService.currentURL, '/'); + this.assertText('Parent'); + }); + } + + '@test respects the usage of a different rootURL'(assert) { + this.router.reopen({ + rootURL: '/app/' + }); + return this.visit('/app').then(() => { + return this.routerService.recognizeAndLoad('/app/child/'); + }).then(routeInfoWithAttributes => { + assert.ok(routeInfoWithAttributes); + var { + name, + localName, + parent + } = routeInfoWithAttributes; + assert.equal(name, 'parent.child'); + assert.equal(localName, 'child'); + assert.equal(parent.name, 'parent'); + }); + } + + '@test must include rootURL'() { + this.router.reopen({ + rootURL: '/app/' + }); + return this.visit('/app').then(() => { + expectAssertion(() => { + this.routerService.recognizeAndLoad('/dynamic-with-child/123/1?a=b'); + }, 'You must pass a url that begins with the application\'s rootURL "/app/"'); + }); + } + + '@test rejects if url is not recognized'(assert) { + this.addTemplate('parent', 'Parent{{outlet}}'); + this.addTemplate('parent.child', 'Child'); + this.add('route:parent.child', _routing.Route.extend({ + model() { + return { + name: 'child', + data: ['stuff'] + }; + } + + })); + return this.visit('/').then(() => { + return this.routerService.recognizeAndLoad('/foo'); + }).then(() => { + assert.ok(false, 'never'); + }, reason => { + assert.equal(reason, 'URL /foo was not recognized'); + }); + } + + '@test rejects if there is an unhandled error'(assert) { + this.addTemplate('parent', 'Parent{{outlet}}'); + this.addTemplate('parent.child', 'Child'); + this.add('route:parent.child', _routing.Route.extend({ + model() { + throw Error('Unhandled'); + } + + })); + return this.visit('/').then(() => { + return this.routerService.recognizeAndLoad('/child'); + }).then(() => { + assert.ok(false, 'never'); + }, err => { + assert.equal(err.message, 'Unhandled'); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/refresh_test", ["@ember/-internals/routing", "@ember/canary-features", "internal-test-helpers"], function (_routing, _canaryFeatures, _internalTestHelpers) { + "use strict"; + + if (_canaryFeatures.EMBER_ROUTING_ROUTER_SERVICE_REFRESH) { + (0, _internalTestHelpers.moduleFor)('Router Service - refresh', class extends _internalTestHelpers.RouterTestCase { + async ['@test RouterService#refresh can be used to re-run the model hooks of active routes'](assert) { + var parentCounter = 0; + this.add('route:parent', class extends _routing.Route { + model() { + ++parentCounter; + } + + }); + var childCounter = 0; + this.add('route:parent.child', class extends _routing.Route { + model() { + ++childCounter; + } + + }); + var sisterCounter = 0; + this.add('route:parent.sister', class extends _routing.Route { + model() { + ++sisterCounter; + } + + }); + await this.visit('/'); + assert.equal(parentCounter, 1); + assert.equal(childCounter, 0); + assert.equal(sisterCounter, 0); + await this.routerService.refresh(); + assert.equal(parentCounter, 2); + assert.equal(childCounter, 0); + assert.equal(sisterCounter, 0); + await this.routerService.refresh('application'); + assert.equal(parentCounter, 3); + assert.equal(childCounter, 0); + assert.equal(sisterCounter, 0); + await this.routerService.transitionTo('parent.child'); + assert.equal(parentCounter, 3); + assert.equal(childCounter, 1); + assert.equal(sisterCounter, 0); + await this.routerService.refresh('parent.child'); + assert.equal(parentCounter, 3); + assert.equal(childCounter, 2); + assert.equal(sisterCounter, 0); + await this.routerService.refresh('parent'); + assert.equal(parentCounter, 4); + assert.equal(childCounter, 3); + assert.equal(sisterCounter, 0); + await this.routerService.transitionTo('parent.sister'); + assert.equal(parentCounter, 4); + assert.equal(childCounter, 3); + assert.equal(sisterCounter, 1); + await this.routerService.refresh(); + assert.equal(parentCounter, 5); + assert.equal(childCounter, 3); + assert.equal(sisterCounter, 2); + } + + async ['@test RouterService#refresh verifies that the provided route exists']() { + await this.visit('/'); + expectAssertion(() => { + this.routerService.refresh('this-route-does-not-exist'); + }, 'The route "this-route-does-not-exist" was not found'); + } + + async ['@test RouterService#refresh verifies that the provided route is active']() { + await this.visit('/'); + expectAssertion(() => { + this.routerService.refresh('parent.child'); + }, 'The route "parent.child" is currently not active'); + } + + }); + } +}); +define("ember/tests/routing/router_service_test/replaceWith_test", ["@ember/-internals/routing", "internal-test-helpers", "router_js", "@ember/controller"], function (_routing, _internalTestHelpers, _router_js, _controller) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - replaceWith', class extends _internalTestHelpers.RouterTestCase { + constructor() { + super(...arguments); + var testCase = this; + testCase.state = []; + this.add('location:test', _routing.NoneLocation.extend({ + setURL(path) { + testCase.state.push(path); + this.set('path', path); + }, + + replaceURL(path) { + testCase.state.splice(testCase.state.length - 1, 1, path); + this.set('path', path); + } + + })); + } + + get routerOptions() { + return { + location: 'test' + }; + } + + ['@test RouterService#replaceWith returns a Transition'](assert) { + assert.expect(1); + var transition; + return this.visit('/').then(() => { + transition = this.routerService.replaceWith('parent.child'); + assert.ok(transition instanceof _router_js.InternalTransition); + return transition; + }); + } + + ['@test RouterService#replaceWith with basic route replaces location'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + return this.routerService.replaceWith('parent.brother'); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child', '/brother']); + }); + } + + ['@test RouterService#replaceWith with basic route using URLs replaces location'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('/child'); + }).then(() => { + return this.routerService.transitionTo('/sister'); + }).then(() => { + return this.routerService.replaceWith('/brother'); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child', '/brother']); + }); + } + + ['@test RouterService#replaceWith transitioning back to previously visited route replaces location'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + return this.routerService.transitionTo('parent.brother'); + }).then(() => { + return this.routerService.replaceWith('parent.sister'); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child', '/sister', '/sister']); + }); + } + + ['@test RouterService#replaceWith with basic query params does not remove query param defaults'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort'], + sort: 'ASC' + })); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.brother'); + }).then(() => { + return this.routerService.replaceWith('parent.sister'); + }).then(() => { + return this.routerService.replaceWith('parent.child', queryParams); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child?sort=ASC']); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/transitionTo_test", ["@ember/service", "@ember/-internals/glimmer", "@ember/-internals/routing", "@ember/controller", "@ember/runloop", "@ember/-internals/metal", "internal-test-helpers", "router_js"], function (_service, _glimmer, _routing, _controller, _runloop, _metal, _internalTestHelpers, _router_js) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Router Service - transitionTo', class extends _internalTestHelpers.RouterTestCase { + constructor() { + super(...arguments); + var testCase = this; + testCase.state = []; + this.add('location:test', _routing.NoneLocation.extend({ + setURL(path) { + testCase.state.push(path); + this.set('path', path); + }, + + replaceURL(path) { + testCase.state.splice(testCase.state.length - 1, 1, path); + this.set('path', path); + } + + })); + } + + get routerOptions() { + return { + location: 'test' + }; + } + + ['@test RouterService#transitionTo returns a Transition'](assert) { + assert.expect(1); + var transition; + return this.visit('/').then(() => { + transition = this.routerService.transitionTo('parent.child'); + assert.ok(transition instanceof _router_js.InternalTransition); + return transition; + }); + } + + ['@test RouterService#transitionTo with basic route updates location'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + return this.routerService.transitionTo('parent.brother'); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child', '/sister', '/brother']); + }); + } + + ['@test RouterService#transitionTo transitioning back to previously visited route updates location'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + return this.routerService.transitionTo('parent.brother'); + }).then(() => { + return this.routerService.transitionTo('parent.sister'); + }).then(() => { + assert.deepEqual(this.state, ['/', '/child', '/sister', '/brother', '/sister']); + }); + } + + ['@test RouterService#transitionTo with basic route'](assert) { + assert.expect(1); + var componentInstance; + this.addTemplate('parent.index', '{{foo-bar}}'); + this.addComponent('foo-bar', { + ComponentClass: _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(); + + componentInstance = this; + }, + + actions: { + transitionToSister() { + (0, _metal.get)(this, 'routerService').transitionTo('parent.sister'); + } + + } + }), + template: `foo-bar` + }); + return this.visit('/').then(() => { + (0, _runloop.run)(function () { + componentInstance.send('transitionToSister'); + }); + assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); + }); + } + + ['@test RouterService#transitionTo with basic route using URL'](assert) { + assert.expect(1); + var componentInstance; + this.addTemplate('parent.index', '{{foo-bar}}'); + this.addComponent('foo-bar', { + ComponentClass: _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(); + + componentInstance = this; + }, + + actions: { + transitionToSister() { + (0, _metal.get)(this, 'routerService').transitionTo('/sister'); + } + + } + }), + template: `foo-bar` + }); + return this.visit('/').then(() => { + (0, _runloop.run)(function () { + componentInstance.send('transitionToSister'); + }); + assert.equal(this.routerService.get('currentRouteName'), 'parent.sister'); + }); + } + + async ['@test RouterService#transitionTo with dynamic segment'](assert) { + assert.expect(3); + var componentInstance; + var dynamicModel = { + id: 1, + contents: 'much dynamicism' + }; + this.addTemplate('parent.index', '{{foo-bar}}'); + this.addTemplate('dynamic', '{{@model.contents}}'); + this.addComponent('foo-bar', { + ComponentClass: _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(); + + componentInstance = this; + }, + + actions: { + transitionToDynamic() { + (0, _metal.get)(this, 'routerService').transitionTo('dynamic', dynamicModel); + } + + } + }), + template: `foo-bar` + }); + await this.visit('/'); + (0, _runloop.run)(function () { + componentInstance.send('transitionToDynamic'); + }); + assert.equal(this.routerService.get('currentRouteName'), 'dynamic'); + assert.equal(this.routerService.get('currentURL'), '/dynamic/1'); + this.assertText('much dynamicism'); + } + + async ['@test RouterService#transitionTo with dynamic segment and model hook'](assert) { + assert.expect(3); + var componentInstance; + var dynamicModel = { + id: 1, + contents: 'much dynamicism' + }; + this.add('route:dynamic', _routing.Route.extend({ + model() { + return dynamicModel; + } + + })); + this.addTemplate('parent.index', '{{foo-bar}}'); + this.addTemplate('dynamic', '{{@model.contents}}'); + this.addComponent('foo-bar', { + ComponentClass: _glimmer.Component.extend({ + routerService: (0, _service.service)('router'), + + init() { + this._super(); + + componentInstance = this; + }, + + actions: { + transitionToDynamic() { + (0, _metal.get)(this, 'routerService').transitionTo('dynamic', 1); + } + + } + }), + template: `foo-bar` + }); + await this.visit('/'); + (0, _runloop.run)(function () { + componentInstance.send('transitionToDynamic'); + }); + assert.equal(this.routerService.get('currentRouteName'), 'dynamic'); + assert.equal(this.routerService.get('currentURL'), '/dynamic/1'); + this.assertText('much dynamicism'); + } + + ['@test RouterService#transitionTo with basic query params does not remove query param defaults'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort'], + sort: 'ASC' + })); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/child?sort=ASC'); + }); + } + + ['@test RouterService#transitionTo passing only queryParams works'](assert) { + assert.expect(2); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort'] + })); + var queryParams = this.buildQueryParams({ + sort: 'DESC' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child'); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/child'); + }).then(() => { + return this.routerService.transitionTo(queryParams); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/child?sort=DESC'); + }); + } + + ['@test RouterService#transitionTo with unspecified query params'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort', 'page', 'category', 'extra'], + sort: 'ASC', + page: null, + category: undefined + })); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/child?sort=ASC'); + }); + } + + ['@test RouterService#transitionTo with aliased query params uses the original provided key'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: { + cont_sort: 'url_sort' + }, + cont_sort: 'ASC' + })); + var queryParams = this.buildQueryParams({ + url_sort: 'ASC' + }); + return this.visit('/').then(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }).then(() => { + assert.equal(this.routerService.get('currentURL'), '/child?url_sort=ASC'); + }); + } + + ['@test RouterService#transitionTo with aliased query params uses the original provided key when controller property name'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: { + cont_sort: 'url_sort' + }, + cont_sort: 'ASC' + })); + var queryParams = this.buildQueryParams({ + cont_sort: 'ASC' + }); + return this.visit('/').then(() => { + expectAssertion(() => { + return this.routerService.transitionTo('parent.child', queryParams); + }, 'You passed the `cont_sort` query parameter during a transition into parent.child, please update to url_sort'); + }); + } + + ['@test RouterService#transitionTo with aliased query params uses the original provided key also when scoped'](assert) { + assert.expect(1); + this.add('route:parent', _routing.Route.extend({ + router: (0, _service.service)(), + + beforeModel() { + // in this call `url_sort` will be scoped (`parent.child:url_sort`) + // when passed into `_hydrateUnsuppliedQueryParams` + this.router.transitionTo('parent.child', { + queryParams: { + url_sort: 'ASC' + } + }); + } + + })); + this.add('route:parent.child', _routing.Route.extend({ + queryParams: { + cont_sort: { + as: 'url_sort' + } + }, + cont_sort: 'ASC' + })); + return this.visit('/').then(() => { + assert.equal(this.routerService.get('currentURL'), '/child?url_sort=ASC'); + }); + } + + ['@test RouterService#transitionTo with application query params when redirecting form a different route'](assert) { + assert.expect(1); + this.add('route:parent.child', _routing.Route.extend({ + router: (0, _service.service)(), + + beforeModel() { + this.router.transitionTo('parent'); + } + + })); + this.add('controller:parent', _controller.default.extend({ + queryParams: ['url_sort'] + })); + return this.visit('/child?url_sort=a').then(() => { + assert.equal(this.routerService.get('currentURL'), '/?url_sort=a'); + }); + } + + }); +}); +define("ember/tests/routing/router_service_test/urlFor_test", ["@ember/controller", "@ember/string", "@ember/-internals/routing", "@ember/-internals/metal", "internal-test-helpers"], function (_controller, _string, _routing, _metal, _internalTestHelpers) { + "use strict"; + + function setupController(app, name) { + var controllerName = `${(0, _string.capitalize)(name)}Controller`; + Object.defineProperty(app, controllerName, { + get() { + throw new Error(`Generating a URL should not require instantiation of a ${controllerName}.`); + } + + }); + } + + (0, _internalTestHelpers.moduleFor)('Router Service - urlFor', class extends _internalTestHelpers.RouterTestCase { + ['@test RouterService#urlFor returns URL for simple route'](assert) { + assert.expect(1); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child'); + assert.equal('/child', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with dynamic segments'](assert) { + assert.expect(1); + setupController(this.application, 'dynamic'); + var dynamicModel = { + id: 1, + contents: 'much dynamicism' + }; + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('dynamic', dynamicModel); + assert.equal('/dynamic/1', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with basic query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: 'bar' + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child', queryParams); + assert.equal('/child?foo=bar', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with basic query params and default value'](assert) { + assert.expect(1); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort'], + sort: 'ASC' + })); + var queryParams = this.buildQueryParams({ + sort: 'ASC' + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child', queryParams); + assert.equal('/child?sort=ASC', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with basic query params and default value with stickyness'](assert) { + assert.expect(2); + this.add('controller:parent.child', _controller.default.extend({ + queryParams: ['sort', 'foo'], + sort: 'ASC' + })); + return this.visit('/child/?sort=DESC').then(() => { + var controller = this.applicationInstance.lookup('controller:parent.child'); + assert.equal((0, _metal.get)(controller, 'sort'), 'DESC', 'sticky is set'); + var queryParams = this.buildQueryParams({ + foo: 'derp' + }); + var actual = this.routerService.urlFor('parent.child', queryParams); + assert.equal(actual, '/child?foo=derp', 'does not use "stickiness"'); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with array as query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + selectedItems: ['a', 'b', 'c'] + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child', queryParams); + assert.equal('/child?selectedItems[]=a&selectedItems[]=b&selectedItems[]=c', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with null query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: null + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child', queryParams); + assert.equal('/child', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with undefined query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: undefined + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('parent.child', queryParams); + assert.equal('/child', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with dynamic segments and basic query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: 'bar' + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('dynamic', { + id: 1 + }, queryParams); + assert.equal('/dynamic/1?foo=bar', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with dynamic segments and array as query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + selectedItems: ['a', 'b', 'c'] + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('dynamic', { + id: 1 + }, queryParams); + assert.equal('/dynamic/1?selectedItems[]=a&selectedItems[]=b&selectedItems[]=c', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with dynamic segments and null query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: null + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('dynamic', { + id: 1 + }, queryParams); + assert.equal('/dynamic/1', expectedURL); + }); + } + + ['@test RouterService#urlFor returns URL for simple route with dynamic segments and undefined query params'](assert) { + assert.expect(1); + var queryParams = this.buildQueryParams({ + foo: undefined + }); + return this.visit('/').then(() => { + var expectedURL = this.routerService.urlFor('dynamic', { + id: 1 + }, queryParams); + assert.equal('/dynamic/1', expectedURL); + }); + } + + ['@test RouterService#urlFor correctly transitions to route via generated path'](assert) { + assert.expect(1); + var expectedURL; + return this.visit('/').then(() => { + expectedURL = this.routerService.urlFor('parent.child'); + return this.routerService.transitionTo(expectedURL); + }).then(() => { + assert.equal(expectedURL, this.routerService.get('currentURL')); + }); + } + + ['@test RouterService#urlFor correctly transitions to route via generated path with dynamic segments'](assert) { + assert.expect(1); + var expectedURL; + var dynamicModel = { + id: 1 + }; + this.add('route:dynamic', _routing.Route.extend({ + model() { + return dynamicModel; + } + + })); + return this.visit('/').then(() => { + expectedURL = this.routerService.urlFor('dynamic', dynamicModel); + return this.routerService.transitionTo(expectedURL); + }).then(() => { + assert.equal(expectedURL, this.routerService.get('currentURL')); + }); + } + + ['@test RouterService#urlFor correctly transitions to route via generated path with query params'](assert) { + assert.expect(1); + var expectedURL; + var actualURL; + var queryParams = this.buildQueryParams({ + foo: 'bar' + }); + return this.visit('/').then(() => { + expectedURL = this.routerService.urlFor('parent.child', queryParams); + return this.routerService.transitionTo(expectedURL); + }).then(() => { + actualURL = `${this.routerService.get('currentURL')}?foo=bar`; + assert.equal(expectedURL, actualURL); + }); + } + + ['@test RouterService#urlFor correctly transitions to route via generated path with dynamic segments and query params'](assert) { + assert.expect(1); + var expectedURL; + var actualURL; + var queryParams = this.buildQueryParams({ + foo: 'bar' + }); + var dynamicModel = { + id: 1 + }; + this.add('route:dynamic', _routing.Route.extend({ + model() { + return dynamicModel; + } + + })); + return this.visit('/').then(() => { + expectedURL = this.routerService.urlFor('dynamic', dynamicModel, queryParams); + return this.routerService.transitionTo(expectedURL); + }).then(() => { + actualURL = `${this.routerService.get('currentURL')}?foo=bar`; + assert.equal(expectedURL, actualURL); + }); + } + + }); +}); +define("ember/tests/routing/substates_test", ["@ember/-internals/runtime", "@ember/-internals/routing", "@ember/controller", "internal-test-helpers"], function (_runtime, _routing, _controller, _internalTestHelpers) { + "use strict"; + + var counter; + + function step(assert, expectedValue, description) { + assert.equal(counter, expectedValue, 'Step ' + expectedValue + ': ' + description); + counter++; + } + + (0, _internalTestHelpers.moduleFor)('Loading/Error Substates', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + counter = 1; + this.addTemplate('application', `
{{outlet}}
`); + this.addTemplate('index', 'INDEX'); + } + + visit(...args) { + return (0, _internalTestHelpers.runTask)(() => super.visit(...args)); + } + + getController(name) { + return this.applicationInstance.lookup(`controller:${name}`); + } + + get currentPath() { + var currentPath; + expectDeprecation(() => { + currentPath = this.getController('application').get('currentPath'); + }, 'Accessing `currentPath` on `controller:application` is deprecated, use the `currentPath` property on `service:router` instead.'); + return currentPath; + } + + ['@test Slow promise from a child route of application enters nested loading state'](assert) { + var turtleDeferred = _runtime.RSVP.defer(); + + this.router.map(function () { + this.route('turtle'); + }); + this.add('route:application', _routing.Route.extend({ + setupController() { + step(assert, 2, 'ApplicationRoute#setupController'); + } + + })); + this.add('route:turtle', _routing.Route.extend({ + model() { + step(assert, 1, 'TurtleRoute#model'); + return turtleDeferred.promise; + } + + })); + this.addTemplate('turtle', 'TURTLE'); + this.addTemplate('loading', 'LOADING'); + var promise = this.visit('/turtle').then(() => { + text = this.$('#app').text(); + assert.equal(text, 'TURTLE', `turtle template has loaded and replaced the loading template`); + }); + var text = this.$('#app').text(); + assert.equal(text, 'LOADING', `The Loading template is nested in application template's outlet`); + turtleDeferred.resolve(); + return promise; + } + + [`@test Slow promises returned from ApplicationRoute#model don't enter LoadingRoute`](assert) { + var appDeferred = _runtime.RSVP.defer(); + + this.add('route:application', _routing.Route.extend({ + model() { + return appDeferred.promise; + } + + })); + this.add('route:loading', _routing.Route.extend({ + setupController() { + assert.ok(false, `shouldn't get here`); + } + + })); + var promise = this.visit('/').then(() => { + var text = this.$('#app').text(); + assert.equal(text, 'INDEX', `index template has been rendered`); + }); + + if (this.element) { + assert.equal(this.element.textContent, ''); + } + + appDeferred.resolve(); + return promise; + } + + [`@test Don't enter loading route unless either route or template defined`](assert) { + var deferred = _runtime.RSVP.defer(); + + this.router.map(function () { + this.route('dummy'); + }); + this.add('route:dummy', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + this.addTemplate('dummy', 'DUMMY'); + return this.visit('/').then(() => { + var promise = this.visit('/dummy').then(() => { + var text = this.$('#app').text(); + assert.equal(text, 'DUMMY', `dummy template has been rendered`); + }); + assert.ok(this.appRouter.currentPath !== 'loading', ` + loading state not entered + `); + deferred.resolve(); + return promise; + }); + } + + ['@test Enter loading route only if loadingRoute is defined'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.router.map(function () { + this.route('dummy'); + }); + this.add('route:dummy', _routing.Route.extend({ + model() { + step(assert, 1, 'DummyRoute#model'); + return deferred.promise; + } + + })); + this.add('route:loading', _routing.Route.extend({ + setupController() { + step(assert, 2, 'LoadingRoute#setupController'); + } + + })); + this.addTemplate('dummy', 'DUMMY'); + return this.visit('/').then(() => { + var promise = this.visit('/dummy').then(() => { + var text = this.$('#app').text(); + assert.equal(text, 'DUMMY', `dummy template has been rendered`); + }); + assert.equal(this.appRouter.currentPath, 'loading', `loading state entered`); + deferred.resolve(); + return promise; + }); + } + + ['@test Enter loading route with correct query parameters'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.router.map(function () { + this.route('dummy'); + }); + this.add('route:dummy', _routing.Route.extend({ + model() { + step(assert, 1, 'DummyRoute#model'); + return deferred.promise; + } + + })); + this.add('controller:application', class extends _controller.default { + constructor(...args) { + super(...args); + this.queryParams = ['qux']; + this.qux = 'initial'; + } + + }); + this.add('route:loading', _routing.Route.extend({ + setupController() { + step(assert, 2, 'LoadingRoute#setupController'); + } + + })); + this.addTemplate('dummy', 'DUMMY'); + return this.visit('/?qux=updated').then(() => { + assert.equal(this.getController('application').qux, 'updated', 'the application controller has the correct qp value'); + var promise = this.visit('/dummy?qux=updated').then(() => { + var text = this.$('#app').text(); + assert.equal(text, 'DUMMY', `dummy template has been rendered`); + assert.equal(this.getController('application').qux, 'updated', 'the application controller has the correct qp value'); + }); + assert.equal(this.appRouter.currentPath, 'loading', `loading state entered`); + assert.equal(this.currentURL, '/dummy?qux=updated', `during loading url reflect the correct state`); + assert.equal(this.getController('application').qux, 'updated', 'the application controller has the correct qp value'); + deferred.resolve(); + return promise; + }); + } + + ['@test Enter child-loading route with correct query parameters'](assert) { + assert.expect(8); + + var deferred = _runtime.RSVP.defer(); + + this.router.map(function () { + this.route('parent', function () { + this.route('child'); + }); + }); + this.add('route:parent.child', _routing.Route.extend({ + model() { + step(assert, 1, 'ChildRoute#model'); + return deferred.promise; + } + + })); + this.add('controller:parent', class extends _controller.default { + constructor(...args) { + super(...args); + this.queryParams = ['qux']; + this.qux = 'initial'; + } + + }); + this.add('route:parent.child_loading', _routing.Route.extend({ + setupController() { + step(assert, 2, 'ChildLoadingRoute#setupController'); + } + + })); + this.addTemplate('parent', 'PARENT {{outlet}}'); + this.addTemplate('parent.child', 'CHILD'); + return this.visit('/parent?qux=updated').then(() => { + assert.equal(this.getController('parent').qux, 'updated', 'in the parent route, the parent controller has the correct qp value'); + var promise = this.visit('/parent/child?qux=updated').then(() => { + var text = this.$('#app').text(); + assert.equal(text, 'PARENT CHILD', `child template has been rendered`); + assert.equal(this.getController('parent').qux, 'updated', 'after entered in the parent.child route, the parent controller has the correct qp value'); + }); + assert.equal(this.appRouter.currentPath, 'parent.child_loading', `child loading state entered`); + assert.equal(this.currentURL, '/parent/child?qux=updated', `during child loading, url reflect the correct state`); + assert.equal(this.getController('parent').qux, 'updated', 'in the child_loading route, the parent controller has the correct qp value'); + deferred.resolve(); + return promise; + }); + } + + ['@test Slow promises returned from ApplicationRoute#model enter ApplicationLoadingRoute if present'](assert) { + var appDeferred = _runtime.RSVP.defer(); + + this.add('route:application', _routing.Route.extend({ + model() { + return appDeferred.promise; + } + + })); + var loadingRouteEntered = false; + this.add('route:application_loading', _routing.Route.extend({ + setupController() { + loadingRouteEntered = true; + } + + })); + var promise = this.visit('/').then(() => { + assert.equal(this.$('#app').text(), 'INDEX', 'index route loaded'); + }); + assert.ok(loadingRouteEntered, 'ApplicationLoadingRoute was entered'); + appDeferred.resolve(); + return promise; + } + + ['@test Slow promises returned from ApplicationRoute#model enter application_loading if template present'](assert) { + var appDeferred = _runtime.RSVP.defer(); + + this.addTemplate('application_loading', ` +
TOPLEVEL LOADING
+ `); + this.add('route:application', _routing.Route.extend({ + model() { + return appDeferred.promise; + } + + })); + var promise = this.visit('/').then(() => { + var length = this.$('#toplevel-loading').length; + text = this.$('#app').text(); + assert.equal(length, 0, `top-level loading view has been entirely removed from the DOM`); + assert.equal(text, 'INDEX', 'index has fully rendered'); + }); + var text = this.$('#toplevel-loading').text(); + assert.equal(text, 'TOPLEVEL LOADING', 'still loading the top level'); + appDeferred.resolve(); + return promise; + } + + ['@test Prioritized substate entry works with preserved-namespace nested routes'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('foo.bar_loading', 'FOOBAR LOADING'); + this.addTemplate('foo.bar.index', 'YAY'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar', { + path: '/bar' + }, function () {}); + }); + }); + this.add('route:foo.bar', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + return this.visit('/').then(() => { + var promise = this.visit('/foo/bar').then(() => { + text = this.$('#app').text(); + assert.equal(text, 'YAY', 'foo.bar.index fully loaded'); + }); + var text = this.$('#app').text(); + assert.equal(text, 'FOOBAR LOADING', `foo.bar_loading was entered (as opposed to something like foo/foo/bar_loading)`); + deferred.resolve(); + return promise; + }); + } + + ['@test Prioritized substate entry works with reset-namespace nested routes'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('bar_loading', 'BAR LOADING'); + this.addTemplate('bar.index', 'YAY'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar', { + path: '/bar', + resetNamespace: true + }, function () {}); + }); + }); + this.add('route:bar', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + return this.visit('/').then(() => { + var promise = this.visit('/foo/bar').then(() => { + text = this.$('#app').text(); + assert.equal(text, 'YAY', 'bar.index fully loaded'); + }); + var text = this.$('#app').text(); + assert.equal(text, 'BAR LOADING', `foo.bar_loading was entered (as opposed to something likefoo/foo/bar_loading)`); + deferred.resolve(); + return promise; + }); + } + + ['@test Prioritized loading substate entry works with preserved-namespace nested routes'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('foo.bar_loading', 'FOOBAR LOADING'); + this.addTemplate('foo.bar', 'YAY'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar'); + }); + }); + this.add('route:foo.bar', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + var promise = this.visit('/foo/bar').then(() => { + text = this.$('#app').text(); + assert.equal(text, 'YAY', 'foo.bar has rendered'); + }); + var text = this.$('#app').text(); + assert.equal(text, 'FOOBAR LOADING', `foo.bar_loading was entered (as opposed to something like foo/foo/bar_loading)`); + deferred.resolve(); + return promise; + } + + async ['@test Prioritized error substate entry works with preserved-namespace nested routes'](assert) { + this.addTemplate('foo.bar_error', 'FOOBAR ERROR: {{@model.msg}}'); + this.addTemplate('foo.bar', 'YAY'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar'); + }); + }); + this.add('route:foo.bar', _routing.Route.extend({ + model() { + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + } + + })); + await this.visit('/'); + await this.visit('/foo/bar'); + assert.equal(this.$('#app').text(), 'FOOBAR ERROR: did it broke?', `foo.bar_error was entered (as opposed to something like foo/foo/bar_error)`); + } + + ['@test Prioritized loading substate entry works with auto-generated index routes'](assert) { + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('foo.index_loading', 'FOO LOADING'); + this.addTemplate('foo.index', 'YAY'); + this.addTemplate('foo', '{{outlet}}'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar'); + }); + }); + this.add('route:foo.index', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + this.add('route:foo', _routing.Route.extend({ + model() { + return true; + } + + })); + var promise = this.visit('/foo').then(() => { + text = this.$('#app').text(); + assert.equal(text, 'YAY', 'foo.index was rendered'); + }); + var text = this.$('#app').text(); + assert.equal(text, 'FOO LOADING', 'foo.index_loading was entered'); + deferred.resolve(); + return promise; + } + + async ['@test Prioritized error substate entry works with auto-generated index routes'](assert) { + this.addTemplate('foo.index_error', 'FOO ERROR: {{@model.msg}}'); + this.addTemplate('foo.index', 'YAY'); + this.addTemplate('foo', '{{outlet}}'); + this.router.map(function () { + this.route('foo', function () { + this.route('bar'); + }); + }); + this.add('route:foo.index', _routing.Route.extend({ + model() { + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + } + + })); + this.add('route:foo', _routing.Route.extend({ + model() { + return true; + } + + })); + await this.visit('/'); + await this.visit('/foo'); + assert.equal(this.$('#app').text(), 'FOO ERROR: did it broke?', 'foo.index_error was entered'); + } + + async ['@test Rejected promises returned from ApplicationRoute transition into top-level application_error'](assert) { + var reject = true; + this.addTemplate('index', '
INDEX
'); + this.add('route:application', _routing.Route.extend({ + init() { + this._super(...arguments); + }, + + model() { + if (reject) { + return _runtime.RSVP.reject({ + msg: 'BAD NEWS BEARS' + }); + } else { + return {}; + } + } + + })); + this.addTemplate('application_error', `

TOPLEVEL ERROR: {{@model.msg}}

`); + await this.visit('/'); + assert.equal(this.$('#toplevel-error').text(), 'TOPLEVEL ERROR: BAD NEWS BEARS', 'toplevel error rendered'); + reject = false; + await this.visit('/'); + assert.equal(this.$('#index').text(), 'INDEX', 'the index route resolved'); + } + + }); + (0, _internalTestHelpers.moduleFor)('Loading/Error Substates - nested routes', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + counter = 1; + this.addTemplate('application', `
{{outlet}}
`); + this.addTemplate('index', 'INDEX'); + this.addTemplate('grandma', 'GRANDMA {{outlet}}'); + this.addTemplate('mom', 'MOM'); + this.router.map(function () { + this.route('grandma', function () { + this.route('mom', { + resetNamespace: true + }, function () { + this.route('sally'); + this.route('this-route-throws'); + }); + this.route('puppies'); + }); + this.route('memere', { + path: '/memere/:seg' + }, function () {}); + }); + } + + getController(name) { + return this.applicationInstance.lookup(`controller:${name}`); + } + + async ['@test ApplicationRoute#currentPath reflects loading state path'](assert) { + await this.visit('/'); + + var momDeferred = _runtime.RSVP.defer(); + + this.addTemplate('grandma.loading', 'GRANDMALOADING'); + this.add('route:mom', _routing.Route.extend({ + model() { + return momDeferred.promise; + } + + })); + var promise = (0, _internalTestHelpers.runTask)(() => this.visit('/grandma/mom')).then(() => { + text = this.$('#app').text(); + assert.equal(text, 'GRANDMA MOM', `Grandma.mom loaded text is displayed`); + assert.equal(this.appRouter.currentPath, 'grandma.mom.index', `currentPath reflects final state`); + }); + var text = this.$('#app').text(); + assert.equal(text, 'GRANDMA GRANDMALOADING', `Grandma.mom loading text displayed`); + assert.equal(this.appRouter.currentPath, 'grandma.loading', `currentPath reflects loading state`); + momDeferred.resolve(); + return promise; + } + + async [`@test Loading actions bubble to root but don't enter substates above pivot `](assert) { + await this.visit('/'); + + var sallyDeferred = _runtime.RSVP.defer(); + + var puppiesDeferred = _runtime.RSVP.defer(); + + this.add('route:application', _routing.Route.extend({ + actions: { + loading() { + assert.ok(true, 'loading action received on ApplicationRoute'); + } + + } + })); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + return sallyDeferred.promise; + } + + })); + this.add('route:grandma.puppies', _routing.Route.extend({ + model() { + return puppiesDeferred.promise; + } + + })); + var promise = this.visit('/grandma/mom/sally'); + assert.equal(this.appRouter.currentPath, 'index', 'Initial route fully loaded'); + sallyDeferred.resolve(); + promise.then(() => { + assert.equal(this.appRouter.currentPath, 'grandma.mom.sally', 'transition completed'); + var visit = this.visit('/grandma/puppies'); + assert.equal(this.appRouter.currentPath, 'grandma.mom.sally', 'still in initial state because the only loading state is above the pivot route'); + return visit; + }).then(() => { + (0, _internalTestHelpers.runTask)(() => puppiesDeferred.resolve()); + assert.equal(this.appRouter.currentPath, 'grandma.puppies', 'Finished transition'); + }); + return promise; + } + + async ['@test Default error event moves into nested route'](assert) { + await this.visit('/'); + this.addTemplate('grandma.error', 'ERROR: {{@model.msg}}'); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error() { + step(assert, 2, 'MomSallyRoute#actions.error'); + return true; + } + + } + })); + await this.visit('/grandma/mom/sally'); + step(assert, 3, 'App finished loading'); + assert.equal(this.$('#app').text(), 'GRANDMA ERROR: did it broke?', 'error bubbles'); + assert.equal(this.appRouter.currentPath, 'grandma.error', 'Initial route fully loaded'); + } + + async [`@test Non-bubbled errors that re-throw aren't swallowed`](assert) { + await this.visit('/'); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error(err) { + // returns undefined which is falsey + throw err; + } + + } + })); + await assert.rejects(this.visit('/grandma/mom/sally'), function (err) { + return err.msg === 'did it broke?'; + }, 'it broke'); + } + + async [`@test Handled errors that re-throw aren't swallowed`](assert) { + await this.visit('/'); + var handledError; + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error(err) { + step(assert, 2, 'MomSallyRoute#actions.error'); + handledError = err; + expectDeprecation(() => { + this.transitionTo('mom.this-route-throws'); + }, /Calling transitionTo on a route is deprecated/); + return false; + } + + } + })); + this.add('route:mom.this-route-throws', _routing.Route.extend({ + model() { + step(assert, 3, 'MomThisRouteThrows#model'); + throw handledError; + } + + })); + await assert.rejects(this.visit('/grandma/mom/sally'), function (err) { + return err.msg === 'did it broke?'; + }, `it broke`); + } + + async ['@test errors that are bubbled are thrown at a higher level if not handled'](assert) { + await this.visit('/'); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error() { + step(assert, 2, 'MomSallyRoute#actions.error'); + return true; + } + + } + })); + await assert.rejects(this.visit('/grandma/mom/sally'), function (err) { + return err.msg == 'did it broke?'; + }, 'Correct error was thrown'); + } + + async [`@test Handled errors that are thrown through rejection aren't swallowed`](assert) { + await this.visit('/'); + var handledError; + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error(err) { + step(assert, 2, 'MomSallyRoute#actions.error'); + handledError = err; + expectDeprecation(() => { + this.transitionTo('mom.this-route-throws'); + }, /Calling transitionTo on a route is deprecated/); + return false; + } + + } + })); + this.add('route:mom.this-route-throws', _routing.Route.extend({ + model() { + step(assert, 3, 'MomThisRouteThrows#model'); + return _runtime.RSVP.reject(handledError); + } + + })); + await assert.rejects(this.visit('/grandma/mom/sally'), function (err) { + return err.msg === 'did it broke?'; + }, 'it broke'); + } + + async ['@test Default error events move into nested route, prioritizing more specifically named error routes - NEW'](assert) { + await this.visit('/'); + this.addTemplate('grandma.error', 'ERROR: {{@model.msg}}'); + this.addTemplate('mom_error', 'MOM ERROR: {{@model.msg}}'); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error() { + step(assert, 2, 'MomSallyRoute#actions.error'); + return true; + } + + } + })); + await this.visit('/grandma/mom/sally'); + step(assert, 3, 'Application finished booting'); + assert.equal(this.$('#app').text(), 'GRANDMA MOM ERROR: did it broke?', 'the more specifically named mome error substate was entered over the other error route'); + assert.equal(this.appRouter.currentPath, 'grandma.mom_error', 'Initial route fully loaded'); + } + + async ['@test Slow promises waterfall on startup'](assert) { + await this.visit('/'); + + var grandmaDeferred = _runtime.RSVP.defer(); + + var sallyDeferred = _runtime.RSVP.defer(); + + this.addTemplate('loading', 'LOADING'); + this.addTemplate('mom', 'MOM {{outlet}}'); + this.addTemplate('mom.loading', 'MOMLOADING'); + this.addTemplate('mom.sally', 'SALLY'); + this.add('route:grandma', _routing.Route.extend({ + model() { + step(assert, 1, 'GrandmaRoute#model'); + return grandmaDeferred.promise; + } + + })); + this.add('route:mom', _routing.Route.extend({ + model() { + step(assert, 2, 'MomRoute#model'); + return {}; + } + + })); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 3, 'SallyRoute#model'); + return sallyDeferred.promise; + }, + + setupController() { + step(assert, 4, 'SallyRoute#setupController'); + } + + })); + var promise = (0, _internalTestHelpers.runTask)(() => this.visit('/grandma/mom/sally')).then(() => { + text = this.$('#app').text(); + assert.equal(text, 'GRANDMA MOM SALLY', `Sally template displayed`); + }); + var text = this.$('#app').text(); + assert.equal(text, 'LOADING', `The loading template is nested in application template's outlet`); + (0, _internalTestHelpers.runTask)(() => grandmaDeferred.resolve()); + text = this.$('#app').text(); + assert.equal(text, 'GRANDMA MOM MOMLOADING', `Mom's child loading route is displayed due to sally's slow promise`); + sallyDeferred.resolve(); + return promise; + } + + async ['@test Enter child loading state of pivot route'](assert) { + await this.visit('/'); + + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('grandma.loading', 'GMONEYLOADING'); + this.add('route:mom.sally', _routing.Route.extend({ + setupController() { + step(assert, 1, 'SallyRoute#setupController'); + } + + })); + this.add('route:grandma.puppies', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + await this.visit('/grandma/mom/sally'); + assert.equal(this.appRouter.currentPath, 'grandma.mom.sally', 'Initial route fully loaded'); + var promise = (0, _internalTestHelpers.runTask)(() => this.visit('/grandma/puppies')).then(() => { + assert.equal(this.appRouter.currentPath, 'grandma.puppies', 'Finished transition'); + }); + assert.equal(this.appRouter.currentPath, 'grandma.loading', `in pivot route's child loading state`); + deferred.resolve(); + return promise; + } + + async [`@test Error events that aren't bubbled don't throw application assertions`](assert) { + await this.visit('/'); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error(err) { + step(assert, 2, 'MomSallyRoute#actions.error'); + assert.equal(err.msg, 'did it broke?', `it didn't break`); + return false; + } + + } + })); + return this.visit('/grandma/mom/sally'); + } + + ['@test Handled errors that bubble can be handled at a higher level'](assert) { + var handledError; + this.add('route:mom', _routing.Route.extend({ + actions: { + error(err) { + step(assert, 3, 'MomRoute#actions.error'); + assert.equal(err, handledError, `error handled and rebubbled is handleable at higher route`); + } + + } + })); + this.add('route:mom.sally', _routing.Route.extend({ + model() { + step(assert, 1, 'MomSallyRoute#model'); + return _runtime.RSVP.reject({ + msg: 'did it broke?' + }); + }, + + actions: { + error(err) { + step(assert, 2, 'MomSallyRoute#actions.error'); + handledError = err; + return true; + } + + } + })); + return this.visit('/grandma/mom/sally'); + } + + async ['@test Setting a query param during a slow transition should work'](assert) { + await this.visit('/'); + + var deferred = _runtime.RSVP.defer(); + + this.addTemplate('memere.loading', 'MMONEYLOADING'); + this.add('route:grandma', _routing.Route.extend({ + beforeModel: function () { + expectDeprecation(() => { + this.transitionTo('memere', 1); + }, /Calling transitionTo on a route is deprecated/); + } + })); + this.add('route:memere', _routing.Route.extend({ + queryParams: { + test: { + defaultValue: 1 + } + } + })); + this.add('route:memere.index', _routing.Route.extend({ + model() { + return deferred.promise; + } + + })); + var promise = (0, _internalTestHelpers.runTask)(() => this.visit('/grandma')).then(() => { + assert.equal(this.appRouter.currentPath, 'memere.index', 'Transition should be complete'); + }); + var memereController = this.getController('memere'); + assert.equal(this.appRouter.currentPath, 'memere.loading', 'Initial route should be loading'); + memereController.set('test', 3); + assert.equal(this.appRouter.currentPath, 'memere.loading', 'Initial route should still be loading'); + assert.equal(memereController.get('test'), 3, 'Controller query param value should have changed'); + deferred.resolve(); + return promise; + } + + }); +}); +define("ember/tests/routing/template_rendering_test", ["@ember/-internals/routing", "@ember/controller", "@ember/-internals/runtime", "internal-test-helpers", "@ember/runloop", "@ember/-internals/glimmer"], function (_routing, _controller, _runtime, _internalTestHelpers, _runloop, _glimmer) { + "use strict"; + + /* eslint-disable no-console */ + var originalConsoleError; + (0, _internalTestHelpers.moduleFor)('Route - template rendering', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + this.addTemplate('home', '

Hours

'); + this.addTemplate('camelot', '

Is a silly place

'); + this.addTemplate('homepage', '

Megatroll

{{this.name}}

'); + this.router.map(function () { + this.route('home', { + path: '/' + }); + }); + originalConsoleError = console.error; + } + + teardown() { + super.teardown(); + console.error = originalConsoleError; + } + + get currentPath() { + var currentPath; + expectDeprecation(() => { + currentPath = this.applicationInstance.lookup('controller:application').get('currentPath'); + }, 'Accessing `currentPath` on `controller:application` is deprecated, use the `currentPath` property on `service:router` instead.'); + return currentPath; + } + + async ['@test warn on URLs not included in the route set'](assert) { + await this.visit('/'); + await assert.rejects(this.visit('/what-is-this-i-dont-even'), /\/what-is-this-i-dont-even/); + } + + ['@test render uses templateName from route'](assert) { + this.addTemplate('the_real_home_template', '

THIS IS THE REAL HOME

'); + this.add('route:home', _routing.Route.extend({ + templateName: 'the_real_home_template' + })); + return this.visit('/').then(() => { + var text = this.$('p').text(); + assert.equal(text, 'THIS IS THE REAL HOME', 'the homepage template was rendered'); + }); + } + + ['@test Generated names can be customized when providing routes with dot notation'](assert) { + assert.expect(4); + this.addTemplate('index', '
Index
'); + this.addTemplate('application', "

Home

{{outlet}}
"); + this.addTemplate('foo', "
{{outlet}}
"); + this.addTemplate('bar', "
{{outlet}}
"); + this.addTemplate('bar.baz', '

{{this.name}}Bottom!

'); + this.router.map(function () { + this.route('foo', { + path: '/top' + }, function () { + this.route('bar', { + path: '/middle', + resetNamespace: true + }, function () { + this.route('baz', { + path: '/bottom' + }); + }); + }); + }); + this.add('route:foo', _routing.Route.extend({ + setupController() { + assert.ok(true, 'FooBarRoute was called'); + return this._super(...arguments); + } + + })); + this.add('route:bar.baz', _routing.Route.extend({ + setupController() { + assert.ok(true, 'BarBazRoute was called'); + return this._super(...arguments); + } + + })); + this.add('controller:bar', _controller.default.extend({ + name: 'Bar' + })); + this.add('controller:bar.baz', _controller.default.extend({ + name: 'BarBaz' + })); + return this.visit('/top/middle/bottom').then(() => { + assert.ok(true, '/top/middle/bottom has been handled'); + var rootElement = document.getElementById('qunit-fixture'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('.main .middle .bottom p')), 'BarBazBottom!', 'The templates were rendered into their appropriate parents'); + }); + } + + ["@test Child routes render into their parent route's template by default"](assert) { + this.addTemplate('index', '
Index
'); + this.addTemplate('application', "

Home

{{outlet}}
"); + this.addTemplate('top', "
{{outlet}}
"); + this.addTemplate('middle', "
{{outlet}}
"); + this.addTemplate('middle.bottom', '

Bottom!

'); + this.router.map(function () { + this.route('top', function () { + this.route('middle', { + resetNamespace: true + }, function () { + this.route('bottom'); + }); + }); + }); + return this.visit('/top/middle/bottom').then(() => { + assert.ok(true, '/top/middle/bottom has been handled'); + var rootElement = document.getElementById('qunit-fixture'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('.main .middle .bottom p')), 'Bottom!', 'The templates were rendered into their appropriate parents'); + }); + } + + ['@test Application template does not duplicate when re-rendered'](assert) { + this.addTemplate('application', '

I render once

{{outlet}}'); + this.router.map(function () { + this.route('posts'); + }); + this.add('route:application', _routing.Route.extend({ + model() { + return (0, _runtime.A)(); + } + + })); + return this.visit('/posts').then(() => { + assert.ok(true, '/posts has been handled'); + var rootElement = document.getElementById('qunit-fixture'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('h3.render-once')), 'I render once'); + }); + } + + ['@test Child routes should render inside the application template if the application template causes a redirect'](assert) { + this.addTemplate('application', '

App

{{outlet}}'); + this.addTemplate('posts', 'posts'); + this.router.map(function () { + this.route('posts'); + this.route('photos'); + }); + this.add('route:application', _routing.Route.extend({ + afterModel() { + expectDeprecation(() => { + this.transitionTo('posts'); + }, /Calling transitionTo on a route is deprecated/); + } + + })); + return this.visit('/posts').then(() => { + var rootElement = document.getElementById('qunit-fixture'); + assert.equal(rootElement.textContent.trim(), 'App posts'); + }); + } + + async ["@test The template is not re-rendered when the route's model changes"](assert) { + this.router.map(function () { + this.route('page', { + path: '/page/:name' + }); + }); + this.add('route:page', _routing.Route.extend({ + model(params) { + return _runtime.Object.create({ + name: params.name + }); + } + + })); + var insertionCount = 0; + this.add('component:foo-bar', _glimmer.Component.extend({ + didInsertElement() { + insertionCount += 1; + } + + })); + this.addTemplate('page', '

{{@model.name}}{{foo-bar}}

'); + var rootElement = document.getElementById('qunit-fixture'); + await this.visit('/page/first'); + assert.ok(true, '/page/first has been handled'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('p')), 'first'); + assert.equal(insertionCount, 1); + await this.visit('/page/second'); + assert.ok(true, '/page/second has been handled'); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('p')), 'second'); + assert.equal(insertionCount, 1, 'view should have inserted only once'); + var router = this.applicationInstance.lookup('router:main'); + await (0, _runloop.run)(() => router.transitionTo('page', _runtime.Object.create({ + name: 'third' + }))); + assert.equal((0, _internalTestHelpers.getTextOf)(rootElement.querySelector('p')), 'third'); + assert.equal(insertionCount, 1, 'view should still have inserted only once'); + } + + ['@test {{outlet}} works when created after initial render'](assert) { + this.addTemplate('sample', 'Hi{{#if this.showTheThing}}{{outlet}}{{/if}}Bye'); + this.addTemplate('sample.inner', 'Yay'); + this.addTemplate('sample.inner2', 'Boo'); + this.router.map(function () { + this.route('sample', { + path: '/' + }, function () { + this.route('inner', { + path: '/' + }); + this.route('inner2', { + path: '/2' + }); + }); + }); + var rootElement; + return this.visit('/').then(() => { + rootElement = document.getElementById('qunit-fixture'); + assert.equal(rootElement.textContent.trim(), 'HiBye', 'initial render'); + (0, _runloop.run)(() => this.applicationInstance.lookup('controller:sample').set('showTheThing', true)); + assert.equal(rootElement.textContent.trim(), 'HiYayBye', 'second render'); + return this.visit('/2'); + }).then(() => { + assert.equal(rootElement.textContent.trim(), 'HiBooBye', 'third render'); + }); + } + + ['@test Components inside an outlet have their didInsertElement hook invoked when the route is displayed'](assert) { + this.addTemplate('index', '{{#if this.showFirst}}{{my-component}}{{else}}{{other-component}}{{/if}}'); + var myComponentCounter = 0; + var otherComponentCounter = 0; + var indexController; + this.router.map(function () { + this.route('index', { + path: '/' + }); + }); + this.add('controller:index', _controller.default.extend({ + showFirst: true + })); + this.add('route:index', _routing.Route.extend({ + setupController(controller) { + indexController = controller; + } + + })); + this.add('component:my-component', _glimmer.Component.extend({ + didInsertElement() { + myComponentCounter++; + } + + })); + this.add('component:other-component', _glimmer.Component.extend({ + didInsertElement() { + otherComponentCounter++; + } + + })); + return this.visit('/').then(() => { + assert.strictEqual(myComponentCounter, 1, 'didInsertElement invoked on displayed component'); + assert.strictEqual(otherComponentCounter, 0, 'didInsertElement not invoked on displayed component'); + (0, _runloop.run)(() => indexController.set('showFirst', false)); + assert.strictEqual(myComponentCounter, 1, 'didInsertElement not invoked on displayed component'); + assert.strictEqual(otherComponentCounter, 1, 'didInsertElement invoked on displayed component'); + }); + } + + }); +}); +define("ember/tests/routing/toplevel_dom_test", ["@ember/-internals/environment", "internal-test-helpers"], function (_environment, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Top Level DOM Structure', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(...arguments); + this._APPLICATION_TEMPLATE_WRAPPER = _environment.ENV._APPLICATION_TEMPLATE_WRAPPER; + } + + teardown() { + super.teardown(); + _environment.ENV._APPLICATION_TEMPLATE_WRAPPER = this._APPLICATION_TEMPLATE_WRAPPER; + } + + ['@test topmost template with wrapper']() { + _environment.ENV._APPLICATION_TEMPLATE_WRAPPER = true; + this.addTemplate('application', 'hello world'); + return this.visit('/').then(() => { + this.assertComponentElement(this.element, { + content: 'hello world' + }); + }); + } + + ['@test topmost template without wrapper']() { + _environment.ENV._APPLICATION_TEMPLATE_WRAPPER = false; + this.addTemplate('application', 'hello world'); + return this.visit('/').then(() => { + this.assertInnerHTML('hello world'); + }); + } + + }); +}); +define("ember/tests/service_injection_test", ["@ember/-internals/owner", "@ember/controller", "@ember/service", "@ember/-internals/runtime", "internal-test-helpers", "@ember/-internals/metal"], function (_owner, _controller, _service, _runtime, _internalTestHelpers, _metal) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('Service Injection', class extends _internalTestHelpers.ApplicationTestCase { + async ['@test Service can be injected and is resolved'](assert) { + this.add('controller:application', _controller.default.extend({ + myService: (0, _service.service)('my-service') + })); + + var MyService = _service.default.extend(); + + this.add('service:my-service', MyService); + this.addTemplate('application', ''); + await this.visit('/'); + var controller = this.applicationInstance.lookup('controller:application'); + assert.ok(controller.get('myService') instanceof MyService); + } + + async ['@test Service can be an object proxy and access owner in init GH#16484'](assert) { + var serviceOwner; + this.add('controller:application', _controller.default.extend({ + myService: (0, _service.service)('my-service') + })); + + var MyService = _service.default.extend(_runtime._ProxyMixin, { + init() { + this._super(...arguments); + + serviceOwner = (0, _owner.getOwner)(this); + } + + }); + + this.add('service:my-service', MyService); + this.addTemplate('application', ''); + var instance = await this.visit('/'); + var controller = this.applicationInstance.lookup('controller:application'); + assert.ok(controller.get('myService') instanceof MyService); + assert.equal(serviceOwner, instance, 'should be able to `getOwner` in init'); + } + + }); + (0, _internalTestHelpers.moduleFor)('Service Injection with ES5 Getters', class extends _internalTestHelpers.ApplicationTestCase { + async ['@test Service can be injected and is resolved without calling `get`'](assert) { + this.add('controller:application', _controller.default.extend({ + myService: (0, _service.service)('my-service') + })); + + var MyService = _service.default.extend({ + name: (0, _metal.computed)(function () { + return 'The service name'; + }) + }); + + this.add('service:my-service', MyService); + this.addTemplate('application', ''); + await this.visit('/'); + var controller = this.applicationInstance.lookup('controller:application'); + assert.ok(controller.myService instanceof MyService); + assert.equal(controller.myService.name, 'The service name', 'service property accessible'); + } + + }); +}); +define("ember/tests/view_instrumentation_test", ["@ember/instrumentation", "internal-test-helpers"], function (_instrumentation, _internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('View Instrumentation', class extends _internalTestHelpers.ApplicationTestCase { + constructor() { + super(); + this.addTemplate('application', `{{outlet}}`); + this.addTemplate('index', `

Index

`); + this.addTemplate('posts', `

Posts

`); + this.router.map(function () { + this.route('posts'); + }); + } + + teardown() { + (0, _instrumentation.reset)(); + super.teardown(); + } + + ['@test Nodes without view instances are instrumented'](assert) { + var called = false; + (0, _instrumentation.subscribe)('render', { + before() { + called = true; + }, + + after() {} + + }); + return this.visit('/').then(() => { + assert.equal(this.textValue(), 'Index', 'It rendered the correct template'); + assert.ok(called, 'Instrumentation called on first render'); + called = false; + return this.visit('/posts'); + }).then(() => { + assert.equal(this.textValue(), 'Posts', 'It rendered the correct template'); + assert.ok(called, 'Instrumentation called on transition to non-view backed route'); + }); + } + + }); +}); +define("internal-test-helpers/index", ["exports", "internal-test-helpers/lib/factory", "internal-test-helpers/lib/build-owner", "internal-test-helpers/lib/confirm-export", "internal-test-helpers/lib/equal-inner-html", "internal-test-helpers/lib/equal-tokens", "internal-test-helpers/lib/module-for", "internal-test-helpers/lib/strip", "internal-test-helpers/lib/apply-mixins", "internal-test-helpers/lib/get-text-of", "internal-test-helpers/lib/ember-dev/deprecation", "internal-test-helpers/lib/define-template-values", "internal-test-helpers/lib/compile", "internal-test-helpers/lib/matchers", "internal-test-helpers/lib/run", "internal-test-helpers/lib/test-context", "internal-test-helpers/lib/test-cases/abstract", "internal-test-helpers/lib/test-cases/abstract-application", "internal-test-helpers/lib/test-cases/application", "internal-test-helpers/lib/test-cases/query-param", "internal-test-helpers/lib/test-cases/rendering", "internal-test-helpers/lib/test-cases/router-non-application", "internal-test-helpers/lib/test-cases/router", "internal-test-helpers/lib/test-cases/autoboot-application", "internal-test-helpers/lib/test-resolver", "internal-test-helpers/lib/browser-detect", "internal-test-helpers/lib/registry-check"], function (_exports, _factory, _buildOwner, _confirmExport, _equalInnerHtml, _equalTokens, _moduleFor, _strip, _applyMixins, _getTextOf, _deprecation, _defineTemplateValues, _compile, _matchers, _run, _testContext, _abstract, _abstractApplication, _application, _queryParam, _rendering, _routerNonApplication, _router, _autobootApplication, _testResolver, _browserDetect, _registryCheck) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + Object.defineProperty(_exports, "factory", { + enumerable: true, + get: function () { + return _factory.default; + } + }); + Object.defineProperty(_exports, "buildOwner", { + enumerable: true, + get: function () { + return _buildOwner.default; + } + }); + Object.defineProperty(_exports, "confirmExport", { + enumerable: true, + get: function () { + return _confirmExport.default; + } + }); + Object.defineProperty(_exports, "equalInnerHTML", { + enumerable: true, + get: function () { + return _equalInnerHtml.default; + } + }); + Object.defineProperty(_exports, "equalTokens", { + enumerable: true, + get: function () { + return _equalTokens.default; + } + }); + Object.defineProperty(_exports, "moduleFor", { + enumerable: true, + get: function () { + return _moduleFor.default; + } + }); + Object.defineProperty(_exports, "setupTestClass", { + enumerable: true, + get: function () { + return _moduleFor.setupTestClass; + } + }); + Object.defineProperty(_exports, "strip", { + enumerable: true, + get: function () { + return _strip.default; + } + }); + Object.defineProperty(_exports, "applyMixins", { + enumerable: true, + get: function () { + return _applyMixins.default; + } + }); + Object.defineProperty(_exports, "getTextOf", { + enumerable: true, + get: function () { + return _getTextOf.default; + } + }); + Object.defineProperty(_exports, "expectDeprecation", { + enumerable: true, + get: function () { + return _deprecation.expectDeprecation; + } + }); + Object.defineProperty(_exports, "expectNoDeprecation", { + enumerable: true, + get: function () { + return _deprecation.expectNoDeprecation; + } + }); + Object.defineProperty(_exports, "expectDeprecationAsync", { + enumerable: true, + get: function () { + return _deprecation.expectDeprecationAsync; + } + }); + Object.defineProperty(_exports, "ignoreDeprecation", { + enumerable: true, + get: function () { + return _deprecation.ignoreDeprecation; + } + }); + Object.defineProperty(_exports, "defineComponent", { + enumerable: true, + get: function () { + return _defineTemplateValues.defineComponent; + } + }); + Object.defineProperty(_exports, "defineSimpleHelper", { + enumerable: true, + get: function () { + return _defineTemplateValues.defineSimpleHelper; + } + }); + Object.defineProperty(_exports, "defineSimpleModifier", { + enumerable: true, + get: function () { + return _defineTemplateValues.defineSimpleModifier; + } + }); + Object.defineProperty(_exports, "compile", { + enumerable: true, + get: function () { + return _compile.default; + } + }); + Object.defineProperty(_exports, "equalsElement", { + enumerable: true, + get: function () { + return _matchers.equalsElement; + } + }); + Object.defineProperty(_exports, "classes", { + enumerable: true, + get: function () { + return _matchers.classes; + } + }); + Object.defineProperty(_exports, "styles", { + enumerable: true, + get: function () { + return _matchers.styles; + } + }); + Object.defineProperty(_exports, "regex", { + enumerable: true, + get: function () { + return _matchers.regex; + } + }); + Object.defineProperty(_exports, "runAppend", { + enumerable: true, + get: function () { + return _run.runAppend; + } + }); + Object.defineProperty(_exports, "runDestroy", { + enumerable: true, + get: function () { + return _run.runDestroy; + } + }); + Object.defineProperty(_exports, "runTask", { + enumerable: true, + get: function () { + return _run.runTask; + } + }); + Object.defineProperty(_exports, "runTaskNext", { + enumerable: true, + get: function () { + return _run.runTaskNext; + } + }); + Object.defineProperty(_exports, "runLoopSettled", { + enumerable: true, + get: function () { + return _run.runLoopSettled; + } + }); + Object.defineProperty(_exports, "getContext", { + enumerable: true, + get: function () { + return _testContext.getContext; + } + }); + Object.defineProperty(_exports, "setContext", { + enumerable: true, + get: function () { + return _testContext.setContext; + } + }); + Object.defineProperty(_exports, "unsetContext", { + enumerable: true, + get: function () { + return _testContext.unsetContext; + } + }); + Object.defineProperty(_exports, "AbstractTestCase", { + enumerable: true, + get: function () { + return _abstract.default; + } + }); + Object.defineProperty(_exports, "AbstractApplicationTestCase", { + enumerable: true, + get: function () { + return _abstractApplication.default; + } + }); + Object.defineProperty(_exports, "ApplicationTestCase", { + enumerable: true, + get: function () { + return _application.default; + } + }); + Object.defineProperty(_exports, "QueryParamTestCase", { + enumerable: true, + get: function () { + return _queryParam.default; + } + }); + Object.defineProperty(_exports, "RenderingTestCase", { + enumerable: true, + get: function () { + return _rendering.default; + } + }); + Object.defineProperty(_exports, "RouterNonApplicationTestCase", { + enumerable: true, + get: function () { + return _routerNonApplication.default; + } + }); + Object.defineProperty(_exports, "RouterTestCase", { + enumerable: true, + get: function () { + return _router.default; + } + }); + Object.defineProperty(_exports, "AutobootApplicationTestCase", { + enumerable: true, + get: function () { + return _autobootApplication.default; + } + }); + Object.defineProperty(_exports, "TestResolver", { + enumerable: true, + get: function () { + return _testResolver.default; + } + }); + Object.defineProperty(_exports, "ModuleBasedTestResolver", { + enumerable: true, + get: function () { + return _testResolver.ModuleBasedResolver; + } + }); + Object.defineProperty(_exports, "isEdge", { + enumerable: true, + get: function () { + return _browserDetect.isEdge; + } + }); + Object.defineProperty(_exports, "verifyRegistration", { + enumerable: true, + get: function () { + return _registryCheck.verifyRegistration; + } + }); +}); +define("internal-test-helpers/lib/apply-mixins", ["exports", "internal-test-helpers/lib/get-all-property-names"], function (_exports, _getAllPropertyNames) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = applyMixins; + + function isGenerator(mixin) { + return Array.isArray(mixin.cases) && typeof mixin.generate === 'function'; + } + + function applyMixins(TestClass, ...mixins) { + mixins.forEach(mixinOrGenerator => { + var mixin; + + if (isGenerator(mixinOrGenerator)) { + var generator = mixinOrGenerator; + mixin = {}; + generator.cases.forEach((value, idx) => { + Object.assign(mixin, generator.generate(value, idx)); + }); + Object.assign(TestClass.prototype, mixin); + } else if (typeof mixinOrGenerator === 'function') { + var properties = (0, _getAllPropertyNames.default)(mixinOrGenerator); + mixin = new mixinOrGenerator(); + properties.forEach(name => { + TestClass.prototype[name] = function () { + return mixin[name].apply(mixin, arguments); + }; + }); + } else { + mixin = mixinOrGenerator; + Object.assign(TestClass.prototype, mixin); + } + }); + return TestClass; + } +}); +define("internal-test-helpers/lib/browser-detect", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.isEdge = void 0; + var isEdge = /Edge/.test(navigator.userAgent); + _exports.isEdge = isEdge; +}); +define("internal-test-helpers/lib/build-owner", ["exports", "@ember/-internals/container", "@ember/-internals/routing", "@ember/application/instance", "@ember/application", "@ember/-internals/runtime"], function (_exports, _container, _routing, _instance, _application, _runtime) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = buildOwner; + + class ResolverWrapper { + constructor(resolver) { + this.resolver = resolver; + } + + create() { + return this.resolver; + } + + } + + function buildOwner(options = {}) { + var ownerOptions = options.ownerOptions || {}; + var resolver = options.resolver; + var bootOptions = options.bootOptions || {}; + + var Owner = _runtime.Object.extend(_runtime.RegistryProxyMixin, _runtime.ContainerProxyMixin); + + var namespace = _runtime.Object.create({ + Resolver: new ResolverWrapper(resolver) + }); + + var fallbackRegistry = _application.default.buildRegistry(namespace); + + fallbackRegistry.register('router:main', _routing.Router); + var registry = new _container.Registry({ + fallback: fallbackRegistry + }); + + _instance.default.setupRegistry(registry, bootOptions); + + var owner = Owner.create({ + __registry__: registry, + __container__: null + }, ownerOptions); + var container = registry.container({ + owner + }); + owner.__container__ = container; + return owner; + } +}); +define("internal-test-helpers/lib/compile", ["exports", "@glimmer/compiler", "@glimmer/opcode-compiler", "ember-template-compiler"], function (_exports, _compiler, _opcodeCompiler, _emberTemplateCompiler) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = compile; + + /** + @module ember + */ + + /** + Uses HTMLBars `compile` function to process a string into a compiled template. + + This is not present in production builds. + + @private + @method compile + @param {String} templateString This is the string to be compiled by HTMLBars. + @param {Object} options This is an options hash to augment the compiler options. + */ + function compile(templateSource, options = {}, scopeValues = {}) { + var _a, _b, _c, _d, _e; + + options.locals = (_a = options.locals) !== null && _a !== void 0 ? _a : Object.keys(scopeValues !== null && scopeValues !== void 0 ? scopeValues : {}); + var [block, usedLocals] = (0, _compiler.precompileJSON)(templateSource, (0, _emberTemplateCompiler.compileOptions)(options)); + var reifiedScopeValues = usedLocals.map(key => scopeValues[key]); + var templateBlock = { + block: JSON.stringify(block), + moduleName: (_d = (_b = options.moduleName) !== null && _b !== void 0 ? _b : (_c = options.meta) === null || _c === void 0 ? void 0 : _c.moduleName) !== null && _d !== void 0 ? _d : '(unknown template module)', + scope: reifiedScopeValues.length > 0 ? () => reifiedScopeValues : null, + isStrictMode: (_e = options.strictMode) !== null && _e !== void 0 ? _e : false + }; + return (0, _opcodeCompiler.templateFactory)(templateBlock); + } +}); +define("internal-test-helpers/lib/confirm-export", ["exports", "require"], function (_exports, _require) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = confirmExport; + + function getDescriptor(obj, path) { + var parts = path.split('.'); + var value = obj; + + for (var i = 0; i < parts.length - 1; i++) { + var part = parts[i]; + value = value[part]; + + if (!value) { + return undefined; + } + } + + var last = parts[parts.length - 1]; + return Object.getOwnPropertyDescriptor(value, last); + } + + function confirmExport(Ember, assert, path, moduleId, exportName) { + try { + var desc; + + if (path !== null) { + desc = getDescriptor(Ember, path); + assert.ok(desc, `the ${path} property exists on the Ember global`); + } else { + desc = null; + } + + if (desc === null) { + var mod = (0, _require.default)(moduleId); + assert.notEqual(mod[exportName], undefined, `${moduleId}#${exportName} is not \`undefined\``); + } else if (typeof exportName === 'string') { + var _mod = (0, _require.default)(moduleId); + + var value = 'value' in desc ? desc.value : desc.get.call(Ember); + assert.equal(value, _mod[exportName], `Ember.${path} is exported correctly`); + assert.notEqual(_mod[exportName], undefined, `Ember.${path} is not \`undefined\``); + } else if ('value' in desc) { + assert.equal(desc.value, exportName.value, `Ember.${path} is exported correctly`); + } else { + var _mod2 = (0, _require.default)(moduleId); + + assert.equal(desc.get, _mod2[exportName.get], `Ember.${path} getter is exported correctly`); + assert.notEqual(desc.get, undefined, `Ember.${path} getter is not undefined`); + + if (exportName.set) { + assert.equal(desc.set, _mod2[exportName.set], `Ember.${path} setter is exported correctly`); + assert.notEqual(desc.set, undefined, `Ember.${path} setter is not undefined`); + } + } + } catch (error) { + assert.pushResult({ + result: false, + message: `An error occurred while testing ${path} is exported from ${moduleId}.`, + source: error + }); + } + } +}); +define("internal-test-helpers/lib/define-template-values", ["exports", "@glimmer/manager", "@glimmer/runtime", "internal-test-helpers/lib/compile"], function (_exports, _manager, _runtime, _compile) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.defineComponent = defineComponent; + _exports.defineSimpleHelper = defineSimpleHelper; + _exports.defineSimpleModifier = defineSimpleModifier; + + class FunctionalHelperManager { + constructor() { + this.capabilities = (0, _manager.helperCapabilities)('3.23', { + hasValue: true + }); + } + + createHelper(fn, args) { + return { + fn, + args + }; + } + + getValue({ + fn, + args + }) { + return fn(...args.positional); + } + + getDebugName(fn) { + return fn.name || '(anonymous function)'; + } + + } + + var FUNCTIONAL_HELPER_MANAGER = new FunctionalHelperManager(); + + var FUNCTIONAL_HELPER_MANAGER_FACTORY = () => FUNCTIONAL_HELPER_MANAGER; + + class FunctionalModifierManager { + constructor() { + this.capabilities = (0, _manager.modifierCapabilities)('3.22'); + } + + createModifier(fn, args) { + return { + fn, + args, + element: undefined, + destructor: undefined + }; + } + + installModifier(state, element) { + state.element = element; + this.setupModifier(state); + } + + updateModifier(state) { + this.destroyModifier(state); + this.setupModifier(state); + } + + setupModifier(state) { + var { + fn, + args, + element + } = state; + state.destructor = fn(element, args.positional, args.named); + } + + destroyModifier(state) { + if (typeof state.destructor === 'function') { + state.destructor(); + } + } + + getDebugName(fn) { + return fn.name || '(anonymous function)'; + } + + } + + var FUNCTIONAL_MODIFIER_MANAGER = new FunctionalModifierManager(); + + var FUNCTIONAL_MODIFIER_MANAGER_FACTORY = () => FUNCTIONAL_MODIFIER_MANAGER; + + function defineComponent(scopeValues, templateSource, definition = (0, _runtime.templateOnlyComponent)()) { + var templateFactory = (0, _compile.default)(templateSource, { + strictMode: scopeValues !== null + }, scopeValues !== null && scopeValues !== void 0 ? scopeValues : {}); + (0, _manager.setComponentTemplate)(templateFactory, definition); + return definition; + } + + function defineSimpleHelper(helperFn) { + return (0, _manager.setHelperManager)(FUNCTIONAL_HELPER_MANAGER_FACTORY, helperFn); + } + + function defineSimpleModifier(modifierFn) { + return (0, _manager.setModifierManager)(FUNCTIONAL_MODIFIER_MANAGER_FACTORY, modifierFn); + } +}); +define("internal-test-helpers/lib/element-helpers", ["exports", "internal-test-helpers/lib/test-context"], function (_exports, _testContext) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.getElement = getElement; + + function getElement() { + var context = (0, _testContext.getContext)(); + + if (!context) { + throw new Error('Test context is not set up.'); + } + + var element = context.element; + + if (!element) { + throw new Error('`element` property on test context is not set up.'); + } + + return element; + } +}); +define("internal-test-helpers/lib/ember-dev/assertion", ["exports", "internal-test-helpers/lib/ember-dev/utils"], function (_exports, _utils) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupAssertionHelpers = setupAssertionHelpers; + var BREAK = {}; + /* + This assertion helper is used to test assertions made using Ember.assert. + It injects two helpers onto `window`: + + - expectAssertion(func: Function, [expectedMessage: String | RegExp]) + + This function calls `func` and asserts that `Ember.assert` is invoked during + the execution. Moreover, it takes a String or a RegExp as a second optional + argument that can be used to test if a specific assertion message was + generated. + + - ignoreAssertion(func: Function) + + This function calls `func` and disables `Ember.assert` during the execution. + In particular, this prevents `Ember.assert` from throw errors that would + disrupt the control flow. + */ + + function setupAssertionHelpers(hooks, env) { + var originalAssertFunc = env.getDebugFunction('assert'); + hooks.beforeEach(function (assert) { + var expectAssertion = (func, expectedMessage) => { + if (!true + /* DEBUG */ + ) { + assert.ok(true, 'Assertions disabled in production builds.'); + return; + } + + var sawCall = false; + var actualMessage = undefined; // The try-catch statement is used to "exit" `func` as soon as + // the first useful assertion has been produced. + + try { + (0, _utils.callWithStub)(env, 'assert', func, (message, test) => { + sawCall = true; + + if ((0, _utils.checkTest)(test)) { + return; + } + + actualMessage = message; + throw BREAK; + }); + } catch (e) { + if (e !== BREAK) { + throw e; + } + } + + check(assert, sawCall, actualMessage, expectedMessage); + }; + + var ignoreAssertion = func => { + (0, _utils.callWithStub)(env, 'assert', func); + }; + + window.expectAssertion = expectAssertion; + window.ignoreAssertion = ignoreAssertion; + }); + hooks.afterEach(function () { + // Edge will occasionally not run finally blocks, so we have to be extra + // sure we restore the original assert function + env.setDebugFunction('assert', originalAssertFunc); + window.expectAssertion = null; + window.ignoreAssertion = null; + }); + } + + function check(assert, sawCall, actualMessage, expectedMessage) { + // Run assertions in an order that is useful when debugging a test failure. + if (!sawCall) { + assert.ok(false, `Expected Ember.assert to be called (Not called with any value).`); + } else if (!actualMessage) { + assert.ok(false, `Expected a failing Ember.assert (Ember.assert called, but without a failing test).`); + } else { + if (expectedMessage) { + if (expectedMessage instanceof RegExp) { + assert.ok(expectedMessage.test(actualMessage), `Expected failing Ember.assert: '${expectedMessage}', but got '${actualMessage}'.`); + } else { + assert.equal(actualMessage, expectedMessage, `Expected failing Ember.assert: '${expectedMessage}', but got '${actualMessage}'.`); + } + } else { + // Positive assertion that assert was called + assert.ok(true, 'Expected a failing Ember.assert.'); + } + } + } +}); +define("internal-test-helpers/lib/ember-dev/containers", ["exports", "@ember/-internals/container"], function (_exports, _container) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupContainersCheck = setupContainersCheck; + var { + _leakTracking: containerLeakTracking + } = _container.Container; + + function setupContainersCheck(hooks) { + hooks.afterEach(function () { + if (containerLeakTracking === undefined) return; + var { + config + } = QUnit; + var { + testName, + testId, + module: { + name: moduleName + }, + finish: originalFinish + } = config.current; + + config.current.finish = function () { + originalFinish.call(this); + originalFinish = undefined; + config.queue.unshift(function () { + if (containerLeakTracking.hasContainers()) { + containerLeakTracking.reset(); // eslint-disable-next-line no-console + + console.assert(false, `Leaked container after test ${moduleName}: ${testName} testId=${testId}`); + } + }); + }; + }); + } +}); +define("internal-test-helpers/lib/ember-dev/debug", ["exports", "internal-test-helpers/lib/ember-dev/method-call-tracker"], function (_exports, _methodCallTracker) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class DebugAssert { + constructor(methodName, env) { + this.methodName = methodName; + this.env = env; + this.tracker = null; + } + + inject() {} + + restore() { + this.reset(); + } + + reset() { + if (this.tracker) { + this.tracker.restoreMethod(); + } + + this.tracker = null; + } + + assert() { + if (this.tracker) { + this.tracker.assert(); + } + } + + runExpectation(func, callback, async = false) { + var originalTracker = null; // When helpers are passed a callback, they get a new tracker context + + if (func) { + originalTracker = this.tracker; + this.tracker = null; + } + + if (!this.tracker) { + this.tracker = new _methodCallTracker.default(this.env, this.methodName); + } // Yield to caller with tracker instance + + + callback(this.tracker); // Once the given callback is invoked, the pending assertions should be + // flushed immediately + + if (func) { + if (async) { + return (async () => { + try { + await func(); + } finally { + this.assert(); + this.reset(); + this.tracker = originalTracker; + } + })(); + } else { + try { + func(); + } finally { + this.assert(); + this.reset(); + this.tracker = originalTracker; + } + } + } + } + + } + + var _default = DebugAssert; + _exports.default = _default; +}); +define("internal-test-helpers/lib/ember-dev/deprecation", ["exports", "@ember/debug", "internal-test-helpers/lib/ember-dev/debug", "internal-test-helpers/lib/ember-dev/utils"], function (_exports, _debug, _debug2, _utils) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupDeprecationHelpers = setupDeprecationHelpers; + _exports.default = _exports.expectNoDeprecationAsync = _exports.expectNoDeprecation = _exports.expectDeprecationAsync = _exports.ignoreDeprecation = _exports.expectDeprecation = void 0; + + function setupDeprecationHelpers(hooks, env) { + var assertion = new DeprecationAssert(env); + hooks.beforeEach(function () { + assertion.reset(); + assertion.inject(); + }); + hooks.afterEach(function () { + assertion.assert(); + assertion.restore(); + }); + } + + var expectDeprecation = () => { + throw new Error('DeprecationAssert: To use `expectDeprecation` in a test you must call `setupDeprecationHelpers` first'); + }; + + _exports.expectDeprecation = expectDeprecation; + + var ignoreDeprecation = () => { + throw new Error('DeprecationAssert: To use `ignoreDeprecation` in a test you must call `setupDeprecationHelpers` first'); + }; + + _exports.ignoreDeprecation = ignoreDeprecation; + + var expectDeprecationAsync = () => { + throw new Error('DeprecationAssert: To use `expectDeprecationAsync` in a test you must call `setupDeprecationHelpers` first'); + }; + + _exports.expectDeprecationAsync = expectDeprecationAsync; + + var expectNoDeprecation = () => { + throw new Error('DeprecationAssert: To use `expectNoDeprecation` in a test you must call `setupDeprecationHelpers` first'); + }; + + _exports.expectNoDeprecation = expectNoDeprecation; + + var expectNoDeprecationAsync = () => { + throw new Error('DeprecationAssert: To use `expectNoDeprecationAsync` in a test you must call `setupDeprecationHelpers` first'); + }; + + _exports.expectNoDeprecationAsync = expectNoDeprecationAsync; + + class DeprecationAssert extends _debug2.default { + constructor(env) { + super('deprecate', env); + } + + inject() { + window.expectNoDeprecation = _exports.expectNoDeprecation = expectNoDeprecation = this.expectNoDeprecation.bind(this); + window.expectNoDeprecationAsync = _exports.expectNoDeprecationAsync = expectNoDeprecationAsync = this.expectNoDeprecationAsync.bind(this); + window.expectDeprecation = _exports.expectDeprecation = expectDeprecation = this.expectDeprecation.bind(this); + window.expectDeprecationAsync = _exports.expectDeprecationAsync = expectDeprecationAsync = this.expectDeprecationAsync.bind(this); + window.ignoreDeprecation = _exports.ignoreDeprecation = ignoreDeprecation = this.ignoreDeprecation.bind(this); + super.inject(); + } + + restore() { + super.restore(); + window.expectNoDeprecation = undefined; + window.expectNoDeprecationAsync = undefined; + window.expectDeprecation = undefined; + window.expectDeprecationAsync = undefined; + window.ignoreDeprecation = undefined; + } // Expects no deprecation to happen within a function, or if no function is + // passed, from the time of calling until the end of the test. + // + // expectNoDeprecation(function() { + // fancyNewThing(); + // }); + // + // expectNoDeprecation(); + // Ember.deprecate("Old And Busted"); + // + + + expectNoDeprecation(func) { + this.runExpectation(func, tracker => { + if (tracker.isExpectingCalls()) { + throw new Error('expectNoDeprecation was called after expectDeprecation was called!'); + } + + tracker.expectNoCalls(); + }); + } // Expects no deprecation to happen within an async function. + // + // expectNoDeprecationAsync(async function() { + // await fancyAsyncThing(); + // }); + // + + + async expectNoDeprecationAsync(func) { + await this.runExpectation(func, tracker => { + if (tracker.isExpectingCalls()) { + throw new Error('expectNoDeprecation was called after expectDeprecation was called!'); + } + + tracker.expectNoCalls(); + }, true); + } + + expectDeprecation(messageOrFuncOrIsEnabled = true, messageOrIsEnabled = true, isEnabled = true) { + var func; + var message; + + if (typeof messageOrFuncOrIsEnabled === 'boolean') { + func = undefined; + isEnabled = messageOrFuncOrIsEnabled; + } else if (typeof messageOrFuncOrIsEnabled === 'function') { + func = messageOrFuncOrIsEnabled; + + if (typeof messageOrIsEnabled === 'boolean') { + isEnabled = messageOrIsEnabled; + } else { + message = messageOrIsEnabled; + } + } else { + (true && !(typeof messageOrIsEnabled === 'boolean') && (0, _debug.assert)(`second argument must be isEnabled flag, got ${messageOrIsEnabled}`, typeof messageOrIsEnabled === 'boolean')); + message = messageOrFuncOrIsEnabled; + isEnabled = messageOrIsEnabled; + } + + if (isEnabled) { + this.runExpectation(func, tracker => { + if (tracker.isExpectingNoCalls()) { + throw new Error('expectDeprecation was called after expectNoDeprecation was called!'); + } + + tracker.expectCall(message, ['id', 'until']); + }); + } else { + this.expectNoDeprecation(func); + } + } + + async expectDeprecationAsync(func, messageOrIsEnabled = true, isEnabled = true) { + var message; + + if (typeof messageOrIsEnabled === 'boolean') { + isEnabled = messageOrIsEnabled; + } else { + message = messageOrIsEnabled; + } + + if (isEnabled) { + await this.runExpectation(func, tracker => { + if (tracker.isExpectingNoCalls()) { + throw new Error('expectDeprecation was called after expectNoDeprecation was called!'); + } + + tracker.expectCall(message, ['id', 'until']); + }, true); + } else { + await this.expectNoDeprecationAsync(func); + } + } + + ignoreDeprecation(func) { + (0, _utils.callWithStub)(this.env, 'deprecate', func); + } + + } + + var _default = DeprecationAssert; + _exports.default = _default; +}); +define("internal-test-helpers/lib/ember-dev/method-call-tracker", ["exports", "internal-test-helpers/lib/ember-dev/utils"], function (_exports, _utils) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class MethodCallTracker { + constructor(env, methodName) { + this._env = env; + this._methodName = methodName; + this._isExpectingNoCalls = false; + this._expectedMessages = []; + this._expectedOptionLists = []; + this._actuals = []; + this._originalMethod = undefined; + } + + stubMethod() { + if (this._originalMethod) { + // Method is already stubbed + return; + } + + var env = this._env; + var methodName = this._methodName; + this._originalMethod = env.getDebugFunction(methodName); + env.setDebugFunction(methodName, (message, test, options) => { + var resultOfTest = (0, _utils.checkTest)(test); + + this._actuals.push([message, resultOfTest, options]); + }); + } + + restoreMethod() { + if (this._originalMethod) { + this._env.setDebugFunction(this._methodName, this._originalMethod); + } + } + + expectCall(message, options) { + this.stubMethod(); + + this._expectedMessages.push(message || /.*/); + + this._expectedOptionLists.push(options); + } + + expectNoCalls() { + this.stubMethod(); + this._isExpectingNoCalls = true; + } + + isExpectingNoCalls() { + return this._isExpectingNoCalls; + } + + isExpectingCalls() { + return !this._isExpectingNoCalls && this._expectedMessages.length; + } + + assert() { + var { + assert + } = QUnit.config.current; + var methodName = this._methodName; + var isExpectingNoCalls = this._isExpectingNoCalls; + var expectedMessages = this._expectedMessages; + var expectedOptionLists = this._expectedOptionLists; + var actuals = this._actuals; + var o, i, j; + + if (!isExpectingNoCalls && expectedMessages.length === 0 && actuals.length === 0) { + return; + } + + if (!true + /* DEBUG */ + ) { + assert.ok(true, `calls to Ember.${methodName} disabled in production builds.`); + return; + } + + if (isExpectingNoCalls) { + var actualMessages = []; + + for (i = 0; i < actuals.length; i++) { + if (!actuals[i][1]) { + actualMessages.push(actuals[i][0]); + } + } + + assert.ok(actualMessages.length === 0, `Expected no Ember.${methodName} calls, got ${actuals.length}: ${actualMessages.join(', ')}`); + return; + } + + var actual; + var match = undefined; + var matched = new Set(); + + for (o = 0; o < expectedMessages.length; o++) { + var expectedMessage = expectedMessages[o]; + var expectedOptionList = expectedOptionLists[o]; + + for (i = 0; i < actuals.length; i++) { + var matchesMessage = false; + var matchesOptionList = false; + actual = actuals[i]; + + if (actual[1] === true) { + continue; + } + + if (expectedMessage instanceof RegExp && expectedMessage.test(actual[0])) { + matchesMessage = true; + } else if (expectedMessage === actual[0]) { + matchesMessage = true; + } + + if (expectedOptionList === undefined) { + matchesOptionList = true; + } else if (actual[2]) { + matchesOptionList = true; + + for (j = 0; j < expectedOptionList.length; j++) { + matchesOptionList = matchesOptionList && Object.prototype.hasOwnProperty.call(actual[2], expectedOptionList[j]); + } + } + + if (matchesMessage && matchesOptionList) { + match = actual; + matched.add(i); + continue; + } + } + + var expectedOptionsMessage = expectedOptionList ? `and options: { ${expectedOptionList.join(', ')} }` : 'and no options'; + var actualOptionsMessage = actual && actual[2] ? `and options: { ${Object.keys(actual[2]).join(', ')} }` : 'and no options'; + + if (!actual) { + assert.ok(false, `Received no Ember.${methodName} calls at all, expecting: ${expectedMessage}`); + } else if (match && !match[1]) { + assert.ok(true, `Received failing Ember.${methodName} call with message: ${match[0]}`); + } else if (match && match[1]) { + assert.ok(false, `Expected failing Ember.${methodName} call, got succeeding with message: ${match[0]}`); + } else if (actual[1]) { + assert.ok(false, `Did not receive failing Ember.${methodName} call matching '${expectedMessage}' ${expectedOptionsMessage}, last was success with '${actual[0]}' ${actualOptionsMessage}`); + } else if (!actual[1]) { + assert.ok(false, `Did not receive failing Ember.${methodName} call matching '${expectedMessage}' ${expectedOptionsMessage}, last was failure with '${actual[0]}' ${actualOptionsMessage}`); + } + } + + for (i = 0; i < actuals.length; i++) { + if (!matched.has(i) && actuals[i][1] !== true) { + assert.ok(false, `Unexpected Ember.${methodName} call: ${actuals[i][0]}`); + } + } + } + + } + + _exports.default = MethodCallTracker; +}); +define("internal-test-helpers/lib/ember-dev/namespaces", ["exports", "@ember/-internals/metal", "@ember/runloop"], function (_exports, _metal, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupNamespacesCheck = setupNamespacesCheck; + + function setupNamespacesCheck(hooks) { + hooks.afterEach(function () { + var { + assert + } = QUnit.config.current; + + if (_metal.NAMESPACES.length > 0) { + assert.ok(false, 'Should not have any NAMESPACES after tests'); + (0, _runloop.run)(() => { + var namespaces = _metal.NAMESPACES.slice(); + + for (var i = 0; i < namespaces.length; i++) { + namespaces[i].destroy(); + } + }); + } + + var keys = Object.keys(_metal.NAMESPACES_BY_ID); + + if (keys.length > 0) { + assert.ok(false, 'Should not have any NAMESPACES_BY_ID after tests'); + + for (var i = 0; i < keys.length; i++) { + delete _metal.NAMESPACES_BY_ID[keys[i]]; + } + } + }); + } +}); +define("internal-test-helpers/lib/ember-dev/observers", ["exports", "@ember/-internals/metal", "@ember/runloop"], function (_exports, _metal, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupObserversCheck = setupObserversCheck; + + function setupObserversCheck(hooks) { + hooks.afterEach(function () { + var { + assert + } = QUnit.config.current; + + if (_metal.ASYNC_OBSERVERS.size > 0) { + assert.ok(false, 'Should not have any ASYNC_OBSERVERS after tests'); + (0, _runloop.run)(() => { + _metal.ASYNC_OBSERVERS.forEach((_, target) => { + _metal.ASYNC_OBSERVERS.delete(target); + + if (isDestroyable(target)) { + try { + target.destroy(); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + } + }); + }); + } + + if (_metal.SYNC_OBSERVERS.size > 0) { + assert.ok(false, 'Should not have any SYNC_OBSERVERS after tests'); + (0, _runloop.run)(() => { + _metal.SYNC_OBSERVERS.forEach((_, target) => { + _metal.SYNC_OBSERVERS.delete(target); + + if (isDestroyable(target)) { + try { + target.destroy(); + } catch (e) { + // eslint-disable-next-line no-console + console.error(e); + } + } + }); + }); + } + }); + } + + function isDestroyable(obj) { + return 'destroy' in obj && typeof obj['destroy'] === 'function'; + } +}); +define("internal-test-helpers/lib/ember-dev/run-loop", ["exports", "@ember/runloop"], function (_exports, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupRunLoopCheck = setupRunLoopCheck; + + // @ts-ignore + function setupRunLoopCheck(hooks) { + hooks.afterEach(function (assert) { + if ((0, _runloop._getCurrentRunLoop)() || (0, _runloop._hasScheduledTimers)()) { + var done = assert.async(); // use a setTimeout to allow the current run loop to flush via autorun + + setTimeout(() => { + // increment expected assertion count for the assertions just below + if (assert['test'].expected !== null) { + assert['test'].expected += 2; + } // if it is _still_ not completed, we have a problem and the test should be fixed + + + assert.ok(!(0, _runloop._hasScheduledTimers)(), 'Ember run should not have scheduled timers at end of test'); + assert.ok(!(0, _runloop._getCurrentRunLoop)(), 'Should not be in a run loop at end of test'); // attempt to recover so the rest of the tests can run + + while ((0, _runloop._getCurrentRunLoop)()) { + (0, _runloop.end)(); + } + + (0, _runloop._cancelTimers)(); + done(); + }, 0); + } + }); + } +}); +define("internal-test-helpers/lib/ember-dev/setup-qunit", ["exports", "ember", "@ember/debug", "internal-test-helpers/lib/ember-dev/assertion", "internal-test-helpers/lib/ember-dev/containers", "internal-test-helpers/lib/ember-dev/deprecation", "internal-test-helpers/lib/ember-dev/namespaces", "internal-test-helpers/lib/ember-dev/observers", "internal-test-helpers/lib/ember-dev/run-loop", "internal-test-helpers/lib/ember-dev/warning"], function (_exports, _ember, _debug, _assertion, _containers, _deprecation, _namespaces, _observers, _runLoop, _warning) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = setupQUnit; + + function setupQUnit() { + var env = { + getDebugFunction: _debug.getDebugFunction, + setDebugFunction: _debug.setDebugFunction + }; + var originalModule = QUnit.module; + + QUnit.module = function (name, callback) { + return originalModule(name, function (hooks) { + (0, _containers.setupContainersCheck)(hooks); + (0, _namespaces.setupNamespacesCheck)(hooks); + (0, _observers.setupObserversCheck)(hooks); + (0, _runLoop.setupRunLoopCheck)(hooks); + (0, _assertion.setupAssertionHelpers)(hooks, env); + (0, _deprecation.setupDeprecationHelpers)(hooks, env); + (0, _warning.setupWarningHelpers)(hooks, env); + callback(hooks); + }); + }; + + QUnit.assert.rejects = async function (promise, expected, message) { + var error; + var prevOnError = _ember.default.onerror; + + _ember.default.onerror = e => { + error = e; + }; + + try { + await promise; + } catch (e) { + error = e; + } + + QUnit.assert.throws(() => { + if (error) { + throw error; + } + }, expected, message); + _ember.default.onerror = prevOnError; + }; + + QUnit.assert.throwsAssertion = function (block, expected, message) { + if (!true + /* DEBUG */ + ) { + QUnit.assert.ok(true, 'Assertions disabled in production builds.'); + return; + } + + return QUnit.assert.throws(block, expected, message); + }; + + QUnit.assert.rejectsAssertion = async function (promise, expected, message) { + if (!true + /* DEBUG */ + ) { + QUnit.assert.ok(true, 'Assertions disabled in production builds.'); + return promise; + } + + await QUnit.assert.rejects(promise, expected, message); + }; + } +}); +define("internal-test-helpers/lib/ember-dev/utils", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.callWithStub = callWithStub; + _exports.checkTest = checkTest; + + function noop() {} + + function callWithStub(env, name, func, debugStub = noop) { + var originalFunc = env.getDebugFunction(name); + + try { + env.setDebugFunction(name, debugStub); + func(); + } finally { + env.setDebugFunction(name, originalFunc); + } + } + + function checkTest(test) { + return typeof test === 'function' ? test() : test; + } +}); +define("internal-test-helpers/lib/ember-dev/warning", ["exports", "internal-test-helpers/lib/ember-dev/debug", "internal-test-helpers/lib/ember-dev/utils"], function (_exports, _debug, _utils) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setupWarningHelpers = setupWarningHelpers; + _exports.default = void 0; + + function setupWarningHelpers(hooks, env) { + var assertion = new WarningAssert(env); + hooks.beforeEach(function () { + assertion.reset(); + assertion.inject(); + }); + hooks.afterEach(function () { + assertion.assert(); + assertion.restore(); + }); + } + + class WarningAssert extends _debug.default { + constructor(env) { + super('warn', env); + } + + inject() { + // Expects no warning to happen within a function, or if no function is + // passed, from the time of calling until the end of the test. + // + // expectNoWarning(function() { + // fancyNewThing(); + // }); + // + // expectNoWarning(); + // Ember.warn("Oh snap, didn't expect that"); + // + var expectNoWarning = func => { + if (typeof func !== 'function') { + func = undefined; + } + + this.runExpectation(func, tracker => { + if (tracker.isExpectingCalls()) { + throw new Error('expectNoWarning was called after expectWarning was called!'); + } + + tracker.expectNoCalls(); + }); + }; // Expect a warning to happen within a function, or if no function is + // passed, from the time of calling until the end of the test. Can be called + // multiple times to assert warnings with different specific messages + // happened. + // + // expectWarning(function() { + // Ember.warn("Times they are a-changin'"); + // }, /* optionalStringOrRegex */); + // + // expectWarning(/* optionalStringOrRegex */); + // Ember.warn("Times definitely be changin'"); + // + + + var expectWarning = (func, message) => { + var actualFunc; + + if (typeof func !== 'function') { + message = func; + actualFunc = undefined; + } else { + actualFunc = func; + } + + this.runExpectation(actualFunc, tracker => { + if (tracker.isExpectingNoCalls()) { + throw new Error('expectWarning was called after expectNoWarning was called!'); + } + + tracker.expectCall(message); + }); + }; + + var ignoreWarning = func => { + (0, _utils.callWithStub)(this.env, 'warn', func); + }; + + window.expectNoWarning = expectNoWarning; + window.expectWarning = expectWarning; + window.ignoreWarning = ignoreWarning; + } + + restore() { + super.restore(); + window.expectWarning = null; + window.expectNoWarning = null; + window.ignoreWarning = null; + } + + } + + var _default = WarningAssert; + _exports.default = _default; +}); +define("internal-test-helpers/lib/equal-inner-html", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = equalInnerHTML; + + // detect side-effects of cloning svg elements in IE9-11 + var ieSVGInnerHTML = (() => { + if (!document.createElementNS) { + return false; + } + + var div = document.createElement('div'); + var node = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + div.appendChild(node); + var clone = div.cloneNode(true); + return clone.innerHTML === ''; + })(); + + function normalizeInnerHTML(actualHTML) { + if (ieSVGInnerHTML) { + // Replace `` with ``, etc. + // drop namespace attribute + // replace self-closing elements + actualHTML = actualHTML.replace(/ xmlns="[^"]+"/, '').replace(/<([^ >]+) [^/>]*\/>/gi, (tag, tagName) => `${tag.slice(0, tag.length - 3)}>`); + } + + return actualHTML; + } + + function equalInnerHTML(assert, fragment, html) { + var actualHTML = normalizeInnerHTML(fragment.innerHTML); + assert.pushResult({ + result: actualHTML === html, + actual: actualHTML, + expected: html + }); + } +}); +define("internal-test-helpers/lib/equal-tokens", ["exports", "simple-html-tokenizer"], function (_exports, _simpleHtmlTokenizer) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = equalTokens; + + function generateTokens(containerOrHTML) { + if (typeof containerOrHTML === 'string') { + return { + tokens: (0, _simpleHtmlTokenizer.tokenize)(containerOrHTML), + html: containerOrHTML + }; + } else { + return { + tokens: (0, _simpleHtmlTokenizer.tokenize)(containerOrHTML.innerHTML), + html: containerOrHTML.innerHTML + }; + } + } + + function normalizeTokens(tokens) { + tokens.forEach(token => { + if (token.type === 'StartTag') { + token.attributes = token.attributes.sort((a, b) => { + if (a[0] > b[0]) { + return 1; + } + + if (a[0] < b[0]) { + return -1; + } + + return 0; + }); + } + }); + } + + function equalTokens(actualContainer, expectedHTML, message = null) { + var actual = generateTokens(actualContainer); + var expected = generateTokens(expectedHTML); + normalizeTokens(actual.tokens); + normalizeTokens(expected.tokens); + var { + assert + } = QUnit.config.current; + var equiv = QUnit.equiv(actual.tokens, expected.tokens); + + if (equiv && expected.html !== actual.html) { + assert.deepEqual(actual.tokens, expected.tokens, message); + } else { + assert.pushResult({ + result: QUnit.equiv(actual.tokens, expected.tokens), + actual: actual.html, + expected: expected.html, + message + }); + } + } +}); +define("internal-test-helpers/lib/factory", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = factory; + + function setProperties(object, properties) { + for (var key in properties) { + if (Object.prototype.hasOwnProperty.call(properties, key)) { + object[key] = properties[key]; + } + } + } + + var guids = 0; + + function factory() { + function Klass(options) { + setProperties(this, options); + this._guid = guids++; + this.isDestroyed = false; + } + + Klass.prototype.constructor = Klass; + + Klass.prototype.destroy = function () { + this.isDestroyed = true; + }; + + Klass.prototype.toString = function () { + return ''; + }; + + Klass.create = create; + Klass.extend = extend; + Klass.reopen = extend; + Klass.reopenClass = reopenClass; + return Klass; + + function create(options) { + return new this.prototype.constructor(options); + } + + function reopenClass(options) { + setProperties(this, options); + } + + function extend(options) { + function Child(options) { + Klass.call(this, options); + } + + var Parent = this; + Child.prototype = new Parent(); + Child.prototype.constructor = Child; + setProperties(Child, Klass); + setProperties(Child.prototype, options); + Child.create = create; + Child.extend = extend; + Child.reopen = extend; + Child.reopenClass = reopenClass; + return Child; + } + } +}); +define("internal-test-helpers/lib/get-all-property-names", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = getAllPropertyNames; + + function getAllPropertyNames(Klass) { + var proto = Klass.prototype; + var properties = new Set(); + + while (proto !== Object.prototype) { + var names = Object.getOwnPropertyNames(proto); + names.forEach(name => properties.add(name)); + proto = Object.getPrototypeOf(proto); + } + + return properties; + } +}); +define("internal-test-helpers/lib/get-text-of", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = getTextOf; + + function getTextOf(elem) { + return elem.textContent.trim(); + } +}); +define("internal-test-helpers/lib/matchers", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.regex = regex; + _exports.classes = classes; + _exports.styles = styles; + _exports.equalsElement = equalsElement; + var HTMLElement = window.HTMLElement; + var MATCHER_BRAND = '3d4ef194-13be-4ccf-8dc7-862eea02c93e'; + + function isMatcher(obj) { + return typeof obj === 'object' && obj !== null && MATCHER_BRAND in obj; + } + + function equalsAttr(expected) { + return { + [MATCHER_BRAND]: true, + + match(actual) { + return expected === actual; + }, + + expected() { + return expected; + }, + + message() { + return `should equal ${this.expected()}`; + } + + }; + } + + function regex(r) { + return { + [MATCHER_BRAND]: true, + + match(v) { + return r.test(v); + }, + + expected() { + return r.toString(); + }, + + message() { + return `should match ${this.expected()}`; + } + + }; + } + + function classes(expected) { + return { + [MATCHER_BRAND]: true, + + match(actual) { + actual = actual.trim(); + return actual && expected.split(/\s+/).sort().join(' ') === actual.trim().split(/\s+/).sort().join(' '); + }, + + expected() { + return expected; + }, + + message() { + return `should match ${this.expected()}`; + } + + }; + } + + function styles(expected) { + return { + [MATCHER_BRAND]: true, + + match(actual) { + // coerce `null` or `undefined` to an empty string + // needed for matching empty styles on IE9 - IE11 + actual = actual || ''; + actual = actual.trim(); + return expected.split(';').map(s => s.trim()).filter(s => s).sort().join('; ') === actual.split(';').map(s => s.trim()).filter(s => s).sort().join('; '); + }, + + expected() { + return expected; + }, + + message() { + return `should match ${this.expected()}`; + } + + }; + } + + function equalsElement(assert, element, tagName, attributes, content) { + assert.pushResult({ + result: element.tagName === tagName.toUpperCase(), + actual: element.tagName.toLowerCase(), + expected: tagName, + message: `expect tagName to be ${tagName}` + }); + var expectedAttrs = {}; + var expectedCount = 0; + + for (var name in attributes) { + var expected = attributes[name]; + + if (expected !== null) { + expectedCount++; + } + + var matcher = isMatcher(expected) ? expected : equalsAttr(expected); + expectedAttrs[name] = matcher; + assert.pushResult({ + result: expectedAttrs[name].match(element.getAttribute(name)), + actual: element.getAttribute(name), + expected: matcher.expected(), + message: `Element's ${name} attribute ${matcher.message()}` + }); + } + + var actualAttributes = {}; + + for (var i = 0, l = element.attributes.length; i < l; i++) { + actualAttributes[element.attributes[i].name] = element.attributes[i].value; + } + + if (!(element instanceof HTMLElement)) { + assert.pushResult({ + result: element instanceof HTMLElement, + message: 'Element must be an HTML Element, not an SVG Element' + }); + } else { + assert.pushResult({ + result: element.attributes.length === expectedCount || !attributes, + actual: element.attributes.length, + expected: expectedCount, + message: `Expected ${expectedCount} attributes; got ${element.outerHTML}` + }); + + if (content !== null) { + assert.pushResult({ + result: element.innerHTML === content, + actual: element.innerHTML, + expected: content, + message: `The element had '${content}' as its content` + }); + } + } + } +}); +define("internal-test-helpers/lib/module-for", ["exports", "@ember/canary-features", "internal-test-helpers/lib/apply-mixins", "internal-test-helpers/lib/get-all-property-names", "internal-test-helpers/lib/test-context", "rsvp", "@glimmer/destroyable"], function (_exports, _canaryFeatures, _applyMixins, _getAllPropertyNames, _testContext, _rsvp, _destroyable) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = moduleFor; + _exports.setupTestClass = setupTestClass; + + /* globals URLSearchParams */ + var ASSERT_DESTROYABLES = (() => { + if (typeof URLSearchParams === 'undefined' || typeof document !== 'object') { + return false; + } + + var queryParams = new URLSearchParams(document.location.search.substring(1)); + var assertDestroyables = queryParams.get('assertDestroyables'); + return assertDestroyables !== null; + })(); + + function moduleFor(description, TestClass, ...mixins) { + QUnit.module(description, function (hooks) { + setupTestClass(hooks, TestClass, ...mixins); + }); + } + + function afterEachFinally() { + (0, _testContext.unsetContext)(); + + if (true + /* DEBUG */ + && ASSERT_DESTROYABLES) { + (0, _destroyable.assertDestroyablesDestroyed)(); + } + } + + function setupTestClass(hooks, TestClass, ...mixins) { + hooks.beforeEach(function (assert) { + if (true + /* DEBUG */ + && ASSERT_DESTROYABLES) { + (0, _destroyable.enableDestroyableTracking)(); + } + + var instance = new TestClass(assert); + this.instance = instance; + (0, _testContext.setContext)(instance); + + if (instance.beforeEach) { + return instance.beforeEach(assert); + } + }); + hooks.afterEach(function () { + var promises = []; + var instance = this.instance; + this.instance = null; + + if (instance.teardown) { + promises.push(instance.teardown()); + } + + if (instance.afterEach) { + promises.push(instance.afterEach()); + } // this seems odd, but actually saves significant time + // in the test suite + // + // returning a promise from a QUnit test always adds a 13ms + // delay to the test, this filtering prevents returning a + // promise when it is not needed + + + var filteredPromises = promises.filter(Boolean); + + if (filteredPromises.length > 0) { + return (0, _rsvp.all)(filteredPromises).finally(afterEachFinally); + } + + afterEachFinally(); + }); + + if (mixins.length > 0) { + (0, _applyMixins.default)(TestClass, ...mixins); + } + + var properties = (0, _getAllPropertyNames.default)(TestClass); + properties.forEach(generateTest); + + function shouldTest(features) { + return features.every(feature => { + if (feature[0] === '!') { + return !(0, _canaryFeatures.isEnabled)(feature.slice(1)); + } else { + return (0, _canaryFeatures.isEnabled)(feature); + } + }); + } + + function generateTest(name) { + if (name.indexOf('@test ') === 0) { + QUnit.test(name.slice(5), function (assert) { + return this.instance[name](assert); + }); + } else if (name.indexOf('@only ') === 0) { + // eslint-disable-next-line qunit/no-only + QUnit.only(name.slice(5), function (assert) { + return this.instance[name](assert); + }); + } else if (name.indexOf('@skip ') === 0) { + QUnit.skip(name.slice(5), function (assert) { + return this.instance[name](assert); + }); + } else { + var match = /^@feature\(([A-Z_a-z-! ,]+)\) /.exec(name); + + if (match) { + var features = match[1].replace(/ /g, '').split(','); + + if (shouldTest(features)) { + QUnit.test(name.slice(match[0].length), function (assert) { + return this.instance[name](assert); + }); + } + } + } + } + } +}); +define("internal-test-helpers/lib/node-query", ["exports", "@ember/debug", "internal-test-helpers/lib/system/synthetic-events"], function (_exports, _debug, _syntheticEvents) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + /* global Node */ + class NodeQuery { + static query(selector, context = document) { + (true && !(context && context instanceof Node) && (0, _debug.assert)(`Invalid second parameter to NodeQuery.query`, context && context instanceof Node)); + return new NodeQuery(toArray(context.querySelectorAll(selector))); + } + + static element(element) { + return new NodeQuery([element]); + } + + constructor(nodes) { + (true && !(Array.isArray(nodes)) && (0, _debug.assert)('NodeQuery must be initialized with a literal array', Array.isArray(nodes))); + this.nodes = nodes; + + for (var i = 0; i < nodes.length; i++) { + this[i] = nodes[i]; + } + + this.length = nodes.length; + Object.freeze(this); + } + + find(selector) { + assertSingle(this); + return this[0].querySelector(selector); + } + + findAll(selector) { + var nodes = []; + this.nodes.forEach(node => { + nodes.push(...node.querySelectorAll(selector)); + }); + return new NodeQuery(nodes); + } + + trigger(eventName, options) { + return this.nodes.map(node => (0, _syntheticEvents.fireEvent)(node, eventName, options)); + } + + click() { + return this.trigger('click'); + } + + focus() { + this.nodes.forEach(_syntheticEvents.focus); + } + + blur() { + this.nodes.forEach(_syntheticEvents.blur); + } + + text() { + return this.nodes.map(node => node.textContent).join(''); + } + + attr(name) { + if (arguments.length !== 1) { + throw new Error('not implemented'); + } + + assertSingle(this); + return this.nodes[0].getAttribute(name); + } + + prop(name, value) { + if (arguments.length > 1) { + return this.setProp(name, value); + } + + assertSingle(this); + return this.nodes[0][name]; + } + + setProp(name, value) { + this.nodes.forEach(node => node[name] = value); + return this; + } + + val(value) { + if (arguments.length === 1) { + return this.setProp('value', value); + } + + return this.prop('value'); + } + + is(selector) { + return this.nodes.every(node => (0, _syntheticEvents.matches)(node, selector)); + } + + hasClass(className) { + return this.is(`.${className}`); + } + + } + + _exports.default = NodeQuery; + + function assertSingle(nodeQuery) { + if (nodeQuery.length !== 1) { + throw new Error(`attr(name) called on a NodeQuery with ${this.nodes.length} elements. Expected one element.`); + } + } + + function toArray(nodes) { + var out = []; + + for (var i = 0; i < nodes.length; i++) { + out.push(nodes[i]); + } + + return out; + } +}); +define("internal-test-helpers/lib/registry-check", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.verifyRegistration = verifyRegistration; + + function verifyRegistration(assert, owner, fullName) { + assert.ok(owner.resolveRegistration(fullName), `has registration: ${fullName}`); + } +}); +define("internal-test-helpers/lib/run", ["exports", "@ember/runloop", "@glimmer/destroyable", "rsvp"], function (_exports, _runloop, _destroyable, _rsvp) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.runAppend = runAppend; + _exports.runDestroy = runDestroy; + _exports.runTask = runTask; + _exports.runTaskNext = runTaskNext; + _exports.runLoopSettled = runLoopSettled; + + function runAppend(view) { + (0, _runloop.run)(view, 'appendTo', document.getElementById('qunit-fixture')); + } + + function runDestroy(toDestroy) { + if (toDestroy) { + (0, _runloop.run)(_destroyable.destroy, toDestroy); + } + } + + function runTask(callback) { + return (0, _runloop.run)(callback); + } + + function runTaskNext() { + return new _rsvp.Promise(resolve => { + return (0, _runloop.next)(resolve); + }); + } // TODO: Find a better name 😎 + + + function runLoopSettled(event) { + return new _rsvp.Promise(function (resolve) { + // Every 5ms, poll for the async thing to have finished + var watcher = setInterval(() => { + // If there are scheduled timers or we are inside of a run loop, keep polling + if ((0, _runloop._hasScheduledTimers)() || (0, _runloop._getCurrentRunLoop)()) { + return; + } // Stop polling + + + clearInterval(watcher); // Synchronously resolve the promise + + resolve(event); + }, 5); + }); + } +}); +define("internal-test-helpers/lib/strip", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = strip; + + function strip([...strings], ...values) { + var str = strings.map((string, index) => { + var interpolated = values[index]; + return string + (interpolated !== undefined ? interpolated : ''); + }).join(''); + return str.split('\n').map(s => s.trim()).join(''); + } +}); +define("internal-test-helpers/lib/system/synthetic-events", ["exports", "@ember/runloop"], function (_exports, _runloop) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.matches = matches; + _exports.click = click; + _exports.focus = focus; + _exports.blur = blur; + _exports.fireEvent = fireEvent; + _exports.elMatches = void 0; + + /* globals Element */ + var DEFAULT_EVENT_OPTIONS = { + canBubble: true, + cancelable: true + }; + var KEYBOARD_EVENT_TYPES = ['keydown', 'keypress', 'keyup']; + var MOUSE_EVENT_TYPES = ['click', 'mousedown', 'mouseup', 'dblclick', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover']; + var elMatches = typeof Element !== 'undefined' && (Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector); + _exports.elMatches = elMatches; + + function matches(el, selector) { + return elMatches.call(el, selector); + } + + function isFocusable(el) { + var focusableTags = ['INPUT', 'BUTTON', 'LINK', 'SELECT', 'A', 'TEXTAREA']; + var { + tagName, + type + } = el; + + if (type === 'hidden') { + return false; + } + + return focusableTags.indexOf(tagName) > -1 || el.contentEditable === 'true'; + } + + function click(el, options = {}) { + (0, _runloop.run)(() => fireEvent(el, 'mousedown', options)); + focus(el); + (0, _runloop.run)(() => fireEvent(el, 'mouseup', options)); + (0, _runloop.run)(() => fireEvent(el, 'click', options)); + } + + function focus(el) { + if (!el) { + return; + } + + if (isFocusable(el)) { + (0, _runloop.run)(null, function () { + var browserIsNotFocused = document.hasFocus && !document.hasFocus(); // Firefox does not trigger the `focusin` event if the window + // does not have focus. If the document doesn't have focus just + // use trigger('focusin') instead. + + if (browserIsNotFocused) { + fireEvent(el, 'focusin'); + } // makes `document.activeElement` be `el`. If the browser is focused, it also fires a focus event + + + el.focus(); // if the browser is not focused the previous `el.focus()` didn't fire an event, so we simulate it + + if (browserIsNotFocused) { + fireEvent(el, 'focus'); + } + }); + } + } + + function blur(el) { + if (isFocusable(el)) { + (0, _runloop.run)(null, function () { + var browserIsNotFocused = document.hasFocus && !document.hasFocus(); + fireEvent(el, 'focusout'); // makes `document.activeElement` be `body`. + // If the browser is focused, it also fires a blur event + + el.blur(); // Chrome/Firefox does not trigger the `blur` event if the window + // does not have focus. If the document does not have focus then + // fire `blur` event via native event. + + if (browserIsNotFocused) { + fireEvent(el, 'blur'); + } + }); + } + } + + function fireEvent(element, type, options = {}) { + if (!element) { + return; + } + + var event; + + if (KEYBOARD_EVENT_TYPES.indexOf(type) > -1) { + event = buildKeyboardEvent(type, options); + } else if (MOUSE_EVENT_TYPES.indexOf(type) > -1) { + var rect = element.getBoundingClientRect(); + var x = rect.left + 1; + var y = rect.top + 1; + var simulatedCoordinates = { + screenX: x + 5, + screenY: y + 95, + clientX: x, + clientY: y + }; + event = buildMouseEvent(type, Object.assign(simulatedCoordinates, options)); + } else { + event = buildBasicEvent(type, options); + } + + element.dispatchEvent(event); + return event; + } + + function buildBasicEvent(type, options = {}) { + var event = document.createEvent('Events'); + event.initEvent(type, true, true); + Object.assign(event, options); + return event; + } + + function buildMouseEvent(type, options = {}) { + var event; + + try { + event = document.createEvent('MouseEvents'); + var eventOpts = Object.assign({}, DEFAULT_EVENT_OPTIONS, options); + event.initMouseEvent(type, eventOpts.canBubble, eventOpts.cancelable, window, eventOpts.detail, eventOpts.screenX, eventOpts.screenY, eventOpts.clientX, eventOpts.clientY, eventOpts.ctrlKey, eventOpts.altKey, eventOpts.shiftKey, eventOpts.metaKey, eventOpts.button, eventOpts.relatedTarget); + } catch (e) { + event = buildBasicEvent(type, options); + } + + return event; + } + + function buildKeyboardEvent(type, options = {}) { + var event; + + try { + event = document.createEvent('KeyEvents'); + var eventOpts = Object.assign({}, DEFAULT_EVENT_OPTIONS, options); + event.initKeyEvent(type, eventOpts.canBubble, eventOpts.cancelable, window, eventOpts.ctrlKey, eventOpts.altKey, eventOpts.shiftKey, eventOpts.metaKey, eventOpts.keyCode, eventOpts.charCode); + } catch (e) { + event = buildBasicEvent(type, options); + } + + return event; + } +}); +define("internal-test-helpers/lib/test-cases/abstract-application", ["exports", "ember-template-compiler", "@ember/-internals/environment", "internal-test-helpers/lib/test-cases/abstract", "internal-test-helpers/lib/run"], function (_exports, _emberTemplateCompiler, _environment, _abstract, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class AbstractApplicationTestCase extends _abstract.default { + _ensureInstance(bootOptions) { + if (this._applicationInstancePromise) { + return this._applicationInstancePromise; + } + + return this._applicationInstancePromise = (0, _run.runTask)(() => this.application.boot()).then(app => { + this.applicationInstance = app.buildInstance(); + return this.applicationInstance.boot(bootOptions); + }); + } + + async visit(url, options) { + // Create the instance + var instance = await this._ensureInstance(options).then(instance => (0, _run.runTask)(() => instance.visit(url))); // Await all asynchronous actions + + await (0, _run.runLoopSettled)(); + return instance; + } + + get element() { + if (this._element) { + return this._element; + } else if (_environment.ENV._APPLICATION_TEMPLATE_WRAPPER) { + return this._element = document.querySelector('#qunit-fixture > div.ember-view'); + } else { + return this._element = document.querySelector('#qunit-fixture'); + } + } + + set element(element) { + this._element = element; + } + + afterEach() { + (0, _run.runDestroy)(this.applicationInstance); + (0, _run.runDestroy)(this.application); + super.teardown(); + } + + get applicationOptions() { + return { + rootElement: '#qunit-fixture' + }; + } + + get routerOptions() { + return { + location: 'none' + }; + } + + get router() { + return this.application.resolveRegistration('router:main'); + } + + compile() + /* string, options */ + { + return (0, _emberTemplateCompiler.compile)(...arguments); + } + + } + + _exports.default = AbstractApplicationTestCase; +}); +define("internal-test-helpers/lib/test-cases/abstract", ["exports", "internal-test-helpers/lib/node-query", "internal-test-helpers/lib/equal-inner-html", "internal-test-helpers/lib/equal-tokens", "internal-test-helpers/lib/element-helpers", "internal-test-helpers/lib/matchers", "internal-test-helpers/lib/run"], function (_exports, _nodeQuery, _equalInnerHtml, _equalTokens, _elementHelpers, _matchers, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + /* global Element */ + var TextNode = window.Text; + var HTMLElement = window.HTMLElement; + var Comment = window.Comment; + + function isMarker(node) { + if (node instanceof Comment && node.textContent === '') { + return true; + } + + if (node instanceof TextNode && node.textContent === '') { + return true; + } + + return false; + } + + class AbstractTestCase { + constructor(assert) { + this.element = null; + this.snapshot = null; + this.assert = assert; + var { + fixture + } = this; + + if (fixture) { + this.setupFixture(fixture); + } + } + + teardown() {} + + afterEach() {} + + setupFixture(innerHTML) { + var fixture = document.getElementById('qunit-fixture'); + fixture.innerHTML = innerHTML; + } // The following methods require `this.element` to work + + + get firstChild() { + return this.nthChild(0); + } + + nthChild(n) { + var i = 0; + var node = (0, _elementHelpers.getElement)().firstChild; + + while (node) { + if (!isMarker(node)) { + i++; + } + + if (i > n) { + break; + } else { + node = node.nextSibling; + } + } + + return node; + } + + get nodesCount() { + var count = 0; + var node = (0, _elementHelpers.getElement)().firstChild; + + while (node) { + if (!isMarker(node)) { + count++; + } + + node = node.nextSibling; + } + + return count; + } + + $(sel) { + if (sel instanceof Element) { + return _nodeQuery.default.element(sel); + } else if (typeof sel === 'string') { + return _nodeQuery.default.query(sel, (0, _elementHelpers.getElement)()); + } else if (sel !== undefined) { + throw new Error(`Invalid this.$(${sel})`); + } else { + return _nodeQuery.default.element((0, _elementHelpers.getElement)()); + } + } + + wrap(element) { + return _nodeQuery.default.element(element); + } + + click(selector) { + var element; + + if (typeof selector === 'string') { + element = (0, _elementHelpers.getElement)().querySelector(selector); + } else { + element = selector; + } + + var event = element.click(); + return (0, _run.runLoopSettled)(event); + } + + textValue() { + return (0, _elementHelpers.getElement)().textContent; + } + + takeSnapshot() { + var snapshot = this.snapshot = []; + var node = (0, _elementHelpers.getElement)().firstChild; + + while (node) { + if (!isMarker(node)) { + snapshot.push(node); + } + + node = node.nextSibling; + } + + return snapshot; + } + + assertText(text) { + this.assert.strictEqual(this.textValue(), text, `#qunit-fixture content should be: \`${text}\``); + } + + assertInnerHTML(html) { + (0, _equalInnerHtml.default)(this.assert, (0, _elementHelpers.getElement)(), html); + } + + assertHTML(html) { + (0, _equalTokens.default)((0, _elementHelpers.getElement)(), html, `#qunit-fixture content should be: \`${html}\``); + } + + assertElement(node, { + ElementType = HTMLElement, + tagName, + attrs = null, + content = null + }) { + if (!(node instanceof ElementType)) { + throw new Error(`Expecting a ${ElementType.name}, but got ${node}`); + } + + (0, _matchers.equalsElement)(this.assert, node, tagName, attrs, content); + } + + assertComponentElement(node, { + ElementType = HTMLElement, + tagName = 'div', + attrs = null, + content = null + }) { + attrs = Object.assign({}, { + id: (0, _matchers.regex)(/^ember\d*$/), + class: (0, _matchers.classes)('ember-view') + }, attrs || {}); + this.assertElement(node, { + ElementType, + tagName, + attrs, + content + }); + } + + assertSameNode(actual, expected) { + this.assert.strictEqual(actual, expected, 'DOM node stability'); + } + + assertInvariants(oldSnapshot, newSnapshot) { + oldSnapshot = oldSnapshot || this.snapshot; + newSnapshot = newSnapshot || this.takeSnapshot(); + this.assert.strictEqual(newSnapshot.length, oldSnapshot.length, 'Same number of nodes'); + + for (var i = 0; i < oldSnapshot.length; i++) { + this.assertSameNode(newSnapshot[i], oldSnapshot[i]); + } + } + + assertPartialInvariants(start, end) { + this.assertInvariants(this.snapshot, this.takeSnapshot().slice(start, end)); + } + + assertStableRerender() { + this.takeSnapshot(); + (0, _run.runTask)(() => this.rerender()); + this.assertInvariants(); + } + + } + + _exports.default = AbstractTestCase; +}); +define("internal-test-helpers/lib/test-cases/application", ["exports", "internal-test-helpers/lib/test-cases/test-resolver-application", "@ember/application", "@ember/-internals/routing", "internal-test-helpers/lib/run"], function (_exports, _testResolverApplication, _application, _routing, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class ApplicationTestCase extends _testResolverApplication.default { + constructor() { + super(...arguments); + var { + applicationOptions + } = this; + this.application = (0, _run.runTask)(this.createApplication.bind(this, applicationOptions)); + this.resolver = this.application.__registry__.resolver; + + if (this.resolver) { + this.resolver.add('router:main', _routing.Router.extend(this.routerOptions)); + } + } + + createApplication(myOptions = {}, MyApplication = _application.default) { + return MyApplication.create(myOptions); + } + + get applicationOptions() { + return Object.assign(super.applicationOptions, { + autoboot: false + }); + } + + get appRouter() { + return this.applicationInstance.lookup('router:main'); + } + + get currentURL() { + return this.appRouter.get('currentURL'); + } + + async transitionTo() { + await this.appRouter.transitionTo(...arguments); + await (0, _run.runLoopSettled)(); + } + + controllerFor(name) { + return this.applicationInstance.lookup(`controller:${name}`); + } + + } + + _exports.default = ApplicationTestCase; +}); +define("internal-test-helpers/lib/test-cases/autoboot-application", ["exports", "internal-test-helpers/lib/test-cases/test-resolver-application", "@ember/application", "@ember/-internals/routing"], function (_exports, _testResolverApplication, _application, _routing) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class AutobootApplicationTestCase extends _testResolverApplication.default { + createApplication(options, MyApplication = _application.default) { + var myOptions = Object.assign(this.applicationOptions, options); + var application = this.application = MyApplication.create(myOptions); + this.resolver = application.__registry__.resolver; + + if (this.resolver) { + this.resolver.add('router:main', _routing.Router.extend(this.routerOptions)); + } + + return application; + } + + visit(url) { + return this.application.boot().then(() => { + return this.applicationInstance.visit(url); + }); + } + + get applicationInstance() { + var { + application + } = this; + + if (!application) { + return undefined; + } + + return application.__deprecatedInstance__; + } + + } + + _exports.default = AutobootApplicationTestCase; +}); +define("internal-test-helpers/lib/test-cases/query-param", ["exports", "@ember/controller", "@ember/-internals/routing", "internal-test-helpers/lib/test-cases/application", "internal-test-helpers/lib/run"], function (_exports, _controller, _routing, _application, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class QueryParamTestCase extends _application.default { + constructor() { + super(...arguments); + var testCase = this; + testCase.expectedPushURL = null; + testCase.expectedReplaceURL = null; + this.add('location:test', _routing.NoneLocation.extend({ + setURL(path) { + if (testCase.expectedReplaceURL) { + testCase.assert.ok(false, 'pushState occurred but a replaceState was expected'); + } + + if (testCase.expectedPushURL) { + testCase.assert.equal(path, testCase.expectedPushURL, 'an expected pushState occurred'); + testCase.expectedPushURL = null; + } + + this.set('path', path); + }, + + replaceURL(path) { + if (testCase.expectedPushURL) { + testCase.assert.ok(false, 'replaceState occurred but a pushState was expected'); + } + + if (testCase.expectedReplaceURL) { + testCase.assert.equal(path, testCase.expectedReplaceURL, 'an expected replaceState occurred'); + testCase.expectedReplaceURL = null; + } + + this.set('path', path); + } + + })); + } + + visitAndAssert(path) { + return this.visit(...arguments).then(() => { + this.assertCurrentPath(path); + }); + } + + getController(name) { + return this.applicationInstance.lookup(`controller:${name}`); + } + + getRoute(name) { + return this.applicationInstance.lookup(`route:${name}`); + } + + get routerOptions() { + return { + location: 'test' + }; + } + + async setAndFlush(obj, prop, value) { + if (typeof prop === 'object') { + obj.setProperties(prop); + } else { + obj.set(prop, value); + } + + await (0, _run.runLoopSettled)(); + } + + assertCurrentPath(path, message = `current path equals '${path}'`) { + this.assert.equal(this.appRouter.get('location.path'), path, message); + } + /** + Sets up a Controller for a given route with a single query param and default + value. Can optionally extend the controller with an object. + @public + @method setSingleQPController + */ + + + setSingleQPController(routeName, param = 'foo', defaultValue = 'bar', options = {}) { + this.add(`controller:${routeName}`, _controller.default.extend({ + queryParams: [param], + [param]: defaultValue + }, options)); + } + /** + Sets up a Controller for a given route with a custom property/url key mapping. + @public + @method setMappedQPController + */ + + + setMappedQPController(routeName, prop = 'page', urlKey = 'parentPage', defaultValue = 1, options = {}) { + this.add(`controller:${routeName}`, _controller.default.extend({ + queryParams: { + [prop]: urlKey + }, + [prop]: defaultValue + }, options)); + } + + } + + _exports.default = QueryParamTestCase; +}); +define("internal-test-helpers/lib/test-cases/rendering", ["exports", "ember-template-compiler", "@ember/-internals/views", "@ember/-internals/glimmer", "internal-test-helpers/lib/test-resolver", "internal-test-helpers/lib/test-cases/abstract", "internal-test-helpers/lib/build-owner", "internal-test-helpers/lib/run"], function (_exports, _emberTemplateCompiler, _views, _glimmer, _testResolver, _abstract, _buildOwner, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + var TextNode = window.Text; + + class RenderingTestCase extends _abstract.default { + constructor() { + super(...arguments); + var bootOptions = this.getBootOptions(); + var owner = this.owner = (0, _buildOwner.default)({ + ownerOptions: this.getOwnerOptions(), + resolver: this.getResolver(), + bootOptions, + viewRegistry: Object.create(null) + }); + owner.register('-view-registry:main', Object.create(null), { + instantiate: false + }); + owner.register('event_dispatcher:main', _views.EventDispatcher); + this.renderer = this.owner.lookup('renderer:-dom'); + this.element = document.querySelector('#qunit-fixture'); + this.component = null; + + if (!bootOptions || bootOptions.isInteractive !== false && bootOptions.skipEventDispatcher !== true) { + owner.lookup('event_dispatcher:main').setup(this.getCustomDispatcherEvents(), this.element); + } + } + + compile() { + return (0, _emberTemplateCompiler.compile)(...arguments); + } + + getCustomDispatcherEvents() { + return {}; + } + + getOwnerOptions() {} + + getBootOptions() {} + + get resolver() { + return this.owner.__registry__.fallback.resolver; + } + + getResolver() { + return new _testResolver.ModuleBasedResolver(); + } + + add(specifier, factory) { + this.resolver.add(specifier, factory); + } + + addTemplate(templateName, templateString) { + if (typeof templateName === 'string') { + this.resolver.add(`template:${templateName}`, this.compile(templateString, { + moduleName: templateName + })); + } else { + this.resolver.add(templateName, this.compile(templateString, { + moduleName: templateName.moduleName + })); + } + } + + addComponent(name, { + ComponentClass = null, + template = null + }) { + if (ComponentClass) { + this.resolver.add(`component:${name}`, ComponentClass); + } + + if (typeof template === 'string') { + this.resolver.add(`template:components/${name}`, this.compile(template, { + moduleName: `components/${name}` + })); + } + } + + afterEach() { + try { + if (this.component) { + (0, _run.runDestroy)(this.component); + } + + if (this.owner) { + (0, _run.runDestroy)(this.owner); + } + } finally { + (0, _glimmer._resetRenderers)(); + } + } + + get context() { + return this.component; + } + + render(templateStr, context = {}) { + var { + owner + } = this; + owner.register('template:-top-level', this.compile(templateStr, { + moduleName: '-top-level' + })); + var attrs = Object.assign({}, context, { + tagName: '', + layoutName: '-top-level' + }); + owner.register('component:-top-level', _glimmer.Component.extend(attrs)); + this.component = owner.lookup('component:-top-level'); + (0, _run.runAppend)(this.component); + } + + rerender() { + this.component.rerender(); + } + + registerHelper(name, funcOrClassBody) { + var type = typeof funcOrClassBody; + + if (type === 'function') { + this.owner.register(`helper:${name}`, (0, _glimmer.helper)(funcOrClassBody)); + } else if (type === 'object' && type !== null) { + this.owner.register(`helper:${name}`, _glimmer.Helper.extend(funcOrClassBody)); + } else { + throw new Error(`Cannot register ${funcOrClassBody} as a helper`); + } + } + + registerCustomHelper(name, definition) { + this.owner.register(`helper:${name}`, definition); + } + + registerComponent(name, { + ComponentClass = _glimmer.Component, + template = null + }) { + var { + owner + } = this; + + if (ComponentClass) { + owner.register(`component:${name}`, ComponentClass); + } + + if (typeof template === 'string') { + owner.register(`template:components/${name}`, this.compile(template, { + moduleName: `my-app/templates/components/${name}.hbs` + })); + } + } + + registerModifier(name, ModifierClass) { + var { + owner + } = this; + owner.register(`modifier:${name}`, ModifierClass); + } + + registerComponentManager(name, manager) { + var owner = this.owner; + owner.register(`component-manager:${name}`, manager); + } + + registerTemplate(name, template) { + var { + owner + } = this; + + if (typeof template === 'string') { + owner.register(`template:${name}`, this.compile(template, { + moduleName: `my-app/templates/${name}.hbs` + })); + } else { + throw new Error(`Registered template "${name}" must be a string`); + } + } + + registerService(name, klass) { + this.owner.register(`service:${name}`, klass); + } + + assertTextNode(node, text) { + if (!(node instanceof TextNode)) { + throw new Error(`Expecting a text node, but got ${node}`); + } + + this.assert.strictEqual(node.textContent, text, 'node.textContent'); + } + + } + + _exports.default = RenderingTestCase; +}); +define("internal-test-helpers/lib/test-cases/router-non-application", ["exports", "ember-template-compiler", "@ember/-internals/views", "@ember/-internals/glimmer", "internal-test-helpers/lib/test-resolver", "internal-test-helpers/lib/test-cases/abstract", "internal-test-helpers/lib/build-owner", "internal-test-helpers/lib/run"], function (_exports, _emberTemplateCompiler, _views, _glimmer, _testResolver, _abstract, _buildOwner, _run) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class RouterNonApplicationTestCase extends _abstract.default { + constructor() { + super(...arguments); + var bootOptions = this.getBootOptions(); + var owner = this.owner = (0, _buildOwner.default)({ + ownerOptions: this.getOwnerOptions(), + resolver: this.getResolver(), + bootOptions, + viewRegistry: Object.create(null) + }); + owner.register('-view-registry:main', Object.create(null), { + instantiate: false + }); + owner.register('event_dispatcher:main', _views.EventDispatcher); + this.renderer = this.owner.lookup('renderer:-dom'); + this.element = document.querySelector('#qunit-fixture'); + this.component = null; + } + + compile() { + return (0, _emberTemplateCompiler.compile)(...arguments); + } + + getOwnerOptions() {} + + getBootOptions() {} + + get resolver() { + return this.owner.__registry__.fallback.resolver; + } + + getResolver() { + return new _testResolver.ModuleBasedResolver(); + } + + add(specifier, factory) { + this.resolver.add(specifier, factory); + } + + addTemplate(templateName, templateString) { + if (typeof templateName === 'string') { + this.resolver.add(`template:${templateName}`, this.compile(templateString, { + moduleName: templateName + })); + } else { + this.resolver.add(templateName, this.compile(templateString, { + moduleName: templateName.moduleName + })); + } + } + + addComponent(name, { + ComponentClass = null, + template = null + }) { + if (ComponentClass) { + this.resolver.add(`component:${name}`, ComponentClass); + } + + if (typeof template === 'string') { + this.resolver.add(`template:components/${name}`, this.compile(template, { + moduleName: `components/${name}` + })); + } + } + + afterEach() { + try { + if (this.component) { + (0, _run.runDestroy)(this.component); + } + + if (this.owner) { + (0, _run.runDestroy)(this.owner); + } + } finally { + (0, _glimmer._resetRenderers)(); + } + } + + render(templateStr, context = {}) { + var { + owner + } = this; + owner.register('template:-top-level', this.compile(templateStr, { + moduleName: '-top-level' + })); + var attrs = Object.assign({}, context, { + tagName: '', + layoutName: '-top-level' + }); + owner.register('component:-top-level', _glimmer.Component.extend(attrs)); + this.component = owner.lookup('component:-top-level'); + (0, _run.runAppend)(this.component); + } + + } + + _exports.default = RouterNonApplicationTestCase; +}); +define("internal-test-helpers/lib/test-cases/router", ["exports", "internal-test-helpers/lib/test-cases/application"], function (_exports, _application) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class RouterTestCase extends _application.default { + constructor() { + super(...arguments); + this.router.map(function () { + this.route('parent', { + path: '/' + }, function () { + this.route('child'); + this.route('sister'); + this.route('brother'); + }); + this.route('dynamic', { + path: '/dynamic/:dynamic_id' + }); + this.route('dynamicWithChild', { + path: '/dynamic-with-child/:dynamic_id' + }, function () { + this.route('child', { + path: '/:child_id' + }); + }); + }); + } + + get routerService() { + return this.applicationInstance.lookup('service:router'); + } + + buildQueryParams(queryParams) { + return { + queryParams + }; + } + + } + + _exports.default = RouterTestCase; +}); +define("internal-test-helpers/lib/test-cases/test-resolver-application", ["exports", "internal-test-helpers/lib/test-cases/abstract-application", "internal-test-helpers/lib/test-resolver", "@ember/-internals/glimmer"], function (_exports, _abstractApplication, _testResolver, _glimmer) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.default = void 0; + + class TestResolverApplicationTestCase extends _abstractApplication.default { + get applicationOptions() { + return Object.assign(super.applicationOptions, { + Resolver: _testResolver.ModuleBasedResolver + }); + } + + add(specifier, factory) { + this.resolver.add(specifier, factory); + } + + addTemplate(templateName, templateString) { + this.resolver.add(`template:${templateName}`, this.compile(templateString, { + moduleName: `my-app/templates/${templateName.replace(/\./g, '/')}.hbs` + })); + } + + addComponent(name, { + ComponentClass = _glimmer.Component, + template = null + }) { + if (ComponentClass) { + this.resolver.add(`component:${name}`, ComponentClass); + } + + if (typeof template === 'string') { + this.resolver.add(`template:components/${name}`, this.compile(template, { + moduleName: `my-app/templates/components/${name}.hbs` + })); + } + } + + } + + _exports.default = TestResolverApplicationTestCase; +}); +define("internal-test-helpers/lib/test-context", ["exports"], function (_exports) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.setContext = setContext; + _exports.getContext = getContext; + _exports.unsetContext = unsetContext; + + var __test_context__; + /** + * Stores the provided context as the "global testing context". + * + * @param {Object} context the context to use + */ + + + function setContext(context) { + __test_context__ = context; + } + /** + * Retrive the "global testing context" as stored by `setContext`. + * + * @returns {Object} the previously stored testing context + */ + + + function getContext() { + return __test_context__; + } + /** + * Clear the "global testing context". + */ + + + function unsetContext() { + __test_context__ = undefined; + } +}); +define("internal-test-helpers/lib/test-resolver", ["exports", "ember-template-compiler"], function (_exports, _emberTemplateCompiler) { + "use strict"; + + Object.defineProperty(_exports, "__esModule", { + value: true + }); + _exports.ModuleBasedResolver = _exports.default = void 0; + var DELIMITER = '%'; + + function serializeKey(specifier, source, namespace) { + var [type, name] = specifier.split(':'); + return `${type}://${[name, namespace ? '[source invalid due to namespace]' : source, namespace].join(DELIMITER)}`; + } + + class Resolver { + constructor() { + this._registered = {}; + } + + resolve(specifier) { + return this._registered[specifier] || this._registered[serializeKey(specifier)]; + } + + add(lookup, factory) { + var key; + + switch (typeof lookup) { + case 'string': + if (lookup.indexOf(':') === -1) { + throw new Error('Specifiers added to the resolver must be in the format of type:name'); + } + + key = serializeKey(lookup); + break; + + case 'object': + key = serializeKey(lookup.specifier, lookup.source, lookup.namespace); + break; + + default: + throw new Error('Specifier string has an unknown type'); + } + + return this._registered[key] = factory; + } + + addTemplate(templateName, template) { + var templateType = typeof template; + + if (templateType !== 'string') { + throw new Error(`You called addTemplate for "${templateName}" with a template argument of type of '${templateType}'. addTemplate expects an argument of an uncompiled template as a string.`); + } + + return this._registered[serializeKey(`template:${templateName}`)] = (0, _emberTemplateCompiler.compile)(template, { + moduleName: `my-app/templates/${templateName}.hbs` + }); + } + + static create() { + return new this(); + } + + } + + var _default = Resolver; + /* + * A resolver with moduleBasedResolver = true handles error and loading + * substates differently than a standard resolver. + */ + + _exports.default = _default; + + class ModuleBasedResolver extends Resolver { + get moduleBasedResolver() { + return true; + } + + } + + _exports.ModuleBasedResolver = ModuleBasedResolver; +}); +define("internal-test-helpers/tests/index-test", ["internal-test-helpers"], function (_internalTestHelpers) { + "use strict"; + + (0, _internalTestHelpers.moduleFor)('internal-test-helpers', class extends _internalTestHelpers.AbstractTestCase { + ['@test module present'](assert) { + assert.ok(true, 'each package needs at least one test to be able to run through `npm test`'); + } + + }); +}); + +}()); +//# sourceMappingURL=ember-tests.map diff --git a/ember-vendored-pr-19806/tests/ember-tests.map b/ember-vendored-pr-19806/tests/ember-tests.map new file mode 100644 index 0000000..bebcdc1 --- /dev/null +++ b/ember-vendored-pr-19806/tests/ember-tests.map @@ -0,0 +1 @@ +{"version":3,"sources":["license.js","loader.js","@ember/-internals/container/tests/container_test.js","@ember/-internals/container/tests/owner_test.js","@ember/-internals/container/tests/registry_test.js","@ember/-internals/extension-support/tests/container_debug_adapter_test.js","@ember/-internals/extension-support/tests/data_adapter_test.js","@ember/-internals/glimmer/tests/integration/application/actions-test.js","@ember/-internals/glimmer/tests/integration/application/debug-render-tree-test.js","@ember/-internals/glimmer/tests/integration/application/engine-test.js","@ember/-internals/glimmer/tests/integration/application/helper-registration-test.js","@ember/-internals/glimmer/tests/integration/application/hot-reload-test.js","@ember/-internals/glimmer/tests/integration/application/rendering-test.js","@ember/-internals/glimmer/tests/integration/components/angle-bracket-invocation-test.js","@ember/-internals/glimmer/tests/integration/components/append-test.js","@ember/-internals/glimmer/tests/integration/components/attribute-bindings-test.js","@ember/-internals/glimmer/tests/integration/components/attrs-lookup-test.js","@ember/-internals/glimmer/tests/integration/components/class-bindings-test.js","@ember/-internals/glimmer/tests/integration/components/component-template-test.js","@ember/-internals/glimmer/tests/integration/components/contextual-components-test.js","@ember/-internals/glimmer/tests/integration/components/curly-components-test.js","@ember/-internals/glimmer/tests/integration/components/dynamic-components-test.js","@ember/-internals/glimmer/tests/integration/components/error-handling-test.js","@ember/-internals/glimmer/tests/integration/components/fragment-components-test.js","@ember/-internals/glimmer/tests/integration/components/input-angle-test.js","@ember/-internals/glimmer/tests/integration/components/input-curly-test.js","@ember/-internals/glimmer/tests/integration/components/instrumentation-compile-test.js","@ember/-internals/glimmer/tests/integration/components/instrumentation-test.js","@ember/-internals/glimmer/tests/integration/components/life-cycle-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/query-params-angle-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/query-params-curly-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/rendering-angle-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/rendering-curly-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/routing-angle-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/routing-curly-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/transitioning-classes-angle-test.js","@ember/-internals/glimmer/tests/integration/components/link-to/transitioning-classes-curly-test.js","@ember/-internals/glimmer/tests/integration/components/render-to-element-test.js","@ember/-internals/glimmer/tests/integration/components/strict-mode-test.js","@ember/-internals/glimmer/tests/integration/components/target-action-test.js","@ember/-internals/glimmer/tests/integration/components/template-only-components-test.js","@ember/-internals/glimmer/tests/integration/components/textarea-angle-test.js","@ember/-internals/glimmer/tests/integration/components/textarea-curly-test.js","@ember/-internals/glimmer/tests/integration/components/to-string-test.js","@ember/-internals/glimmer/tests/integration/components/tracked-test.js","@ember/-internals/glimmer/tests/integration/components/utils-test.js","@ember/-internals/glimmer/tests/integration/components/web-component-fallback-test.js","@ember/-internals/glimmer/tests/integration/components/will-destroy-element-hook-test.js","@ember/-internals/glimmer/tests/integration/content-test.js","@ember/-internals/glimmer/tests/integration/custom-component-manager-test.js","@ember/-internals/glimmer/tests/integration/custom-modifier-manager-test.js","@ember/-internals/glimmer/tests/integration/event-dispatcher-test.js","@ember/-internals/glimmer/tests/integration/helpers/array-test.js","@ember/-internals/glimmer/tests/integration/helpers/closure-action-test.js","@ember/-internals/glimmer/tests/integration/helpers/concat-test.js","@ember/-internals/glimmer/tests/integration/helpers/custom-helper-test.js","@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js","@ember/-internals/glimmer/tests/integration/helpers/fn-test.js","@ember/-internals/glimmer/tests/integration/helpers/get-test.js","@ember/-internals/glimmer/tests/integration/helpers/hash-test.js","@ember/-internals/glimmer/tests/integration/helpers/helper-manager-test.js","@ember/-internals/glimmer/tests/integration/helpers/if-unless-test.js","@ember/-internals/glimmer/tests/integration/helpers/invoke-helper-test.js","@ember/-internals/glimmer/tests/integration/helpers/log-test.js","@ember/-internals/glimmer/tests/integration/helpers/mut-test.js","@ember/-internals/glimmer/tests/integration/helpers/readonly-test.js","@ember/-internals/glimmer/tests/integration/helpers/tracked-test.js","@ember/-internals/glimmer/tests/integration/helpers/unbound-test.js","@ember/-internals/glimmer/tests/integration/helpers/yield-test.js","@ember/-internals/glimmer/tests/integration/input-test.js","@ember/-internals/glimmer/tests/integration/modifiers/on-test.js","@ember/-internals/glimmer/tests/integration/mount-test.js","@ember/-internals/glimmer/tests/integration/outlet-test.js","@ember/-internals/glimmer/tests/integration/refinements-test.js","@ember/-internals/glimmer/tests/integration/render-settled-test.js","@ember/-internals/glimmer/tests/integration/svg-test.js","@ember/-internals/glimmer/tests/integration/syntax/each-in-test.js","@ember/-internals/glimmer/tests/integration/syntax/each-test.js","@ember/-internals/glimmer/tests/integration/syntax/if-unless-test.js","@ember/-internals/glimmer/tests/integration/syntax/let-test.js","@ember/-internals/glimmer/tests/integration/syntax/public-in-element-test.js","@ember/-internals/glimmer/tests/integration/syntax/with-dynamic-var-test.js","@ember/-internals/glimmer/tests/unit/outlet-test.js","@ember/-internals/glimmer/tests/unit/runtime-resolver-cache-test.js","@ember/-internals/glimmer/tests/unit/template-factory-test.js","@ember/-internals/glimmer/tests/utils/debug-stack.js","@ember/-internals/glimmer/tests/utils/glimmerish-component.js","@ember/-internals/glimmer/tests/utils/helpers.js","@ember/-internals/glimmer/tests/utils/shared-conditional-tests.js","@ember/-internals/glimmer/tests/utils/string-test.js","@ember/-internals/meta/tests/listeners_test.js","@ember/-internals/meta/tests/meta_test.js","@ember/-internals/metal/tests/accessors/get_path_test.js","@ember/-internals/metal/tests/accessors/get_properties_test.js","@ember/-internals/metal/tests/accessors/get_test.js","@ember/-internals/metal/tests/accessors/set_path_test.js","@ember/-internals/metal/tests/accessors/set_test.js","@ember/-internals/metal/tests/alias_test.js","@ember/-internals/metal/tests/cached/get_test.js","@ember/-internals/metal/tests/computed_decorator_test.js","@ember/-internals/metal/tests/computed_test.js","@ember/-internals/metal/tests/events_test.js","@ember/-internals/metal/tests/expand_properties_test.js","@ember/-internals/metal/tests/injected_property_test.js","@ember/-internals/metal/tests/is_blank_test.js","@ember/-internals/metal/tests/is_empty_test.js","@ember/-internals/metal/tests/is_none_test.js","@ember/-internals/metal/tests/is_present_test.js","@ember/-internals/metal/tests/libraries_test.js","@ember/-internals/metal/tests/main_test.js","@ember/-internals/metal/tests/mixin/accessor_test.js","@ember/-internals/metal/tests/mixin/apply_test.js","@ember/-internals/metal/tests/mixin/computed_test.js","@ember/-internals/metal/tests/mixin/concatenated_properties_test.js","@ember/-internals/metal/tests/mixin/detect_test.js","@ember/-internals/metal/tests/mixin/introspection_test.js","@ember/-internals/metal/tests/mixin/merged_properties_test.js","@ember/-internals/metal/tests/mixin/method_test.js","@ember/-internals/metal/tests/mixin/observer_test.js","@ember/-internals/metal/tests/mixin/reopen_test.js","@ember/-internals/metal/tests/mixin/without_test.js","@ember/-internals/metal/tests/namespace_search_test.js","@ember/-internals/metal/tests/native_desc_decorator_test.js","@ember/-internals/metal/tests/observer_test.js","@ember/-internals/metal/tests/performance_test.js","@ember/-internals/metal/tests/properties_test.js","@ember/-internals/metal/tests/property_events_test.js","@ember/-internals/metal/tests/set_properties_test.js","@ember/-internals/metal/tests/tracked/classic_classes_test.js","@ember/-internals/metal/tests/tracked/get_test.js","@ember/-internals/metal/tests/tracked/set_test.js","@ember/-internals/metal/tests/tracked/validation_test.js","@ember/-internals/routing/tests/ext/controller_test.js","@ember/-internals/routing/tests/location/auto_location_test.js","@ember/-internals/routing/tests/location/hash_location_test.js","@ember/-internals/routing/tests/location/history_location_test.js","@ember/-internals/routing/tests/location/none_location_test.js","@ember/-internals/routing/tests/location/util_test.js","@ember/-internals/routing/tests/system/cache_test.js","@ember/-internals/routing/tests/system/controller_for_test.js","@ember/-internals/routing/tests/system/dsl_test.js","@ember/-internals/routing/tests/system/route_test.js","@ember/-internals/routing/tests/system/router_test.js","@ember/-internals/routing/tests/utils_test.js","@ember/-internals/runtime/tests/array/any-test.js","@ember/-internals/runtime/tests/array/apply-test.js","@ember/-internals/runtime/tests/array/compact-test.js","@ember/-internals/runtime/tests/array/every-test.js","@ember/-internals/runtime/tests/array/filter-test.js","@ember/-internals/runtime/tests/array/find-test.js","@ember/-internals/runtime/tests/array/firstObject-test.js","@ember/-internals/runtime/tests/array/forEach-test.js","@ember/-internals/runtime/tests/array/includes-test.js","@ember/-internals/runtime/tests/array/indexOf-test.js","@ember/-internals/runtime/tests/array/invoke-test.js","@ember/-internals/runtime/tests/array/isAny-test.js","@ember/-internals/runtime/tests/array/lastIndexOf-test.js","@ember/-internals/runtime/tests/array/lastObject-test.js","@ember/-internals/runtime/tests/array/map-test.js","@ember/-internals/runtime/tests/array/mapBy-test.js","@ember/-internals/runtime/tests/array/objectAt-test.js","@ember/-internals/runtime/tests/array/reduce-test.js","@ember/-internals/runtime/tests/array/reject-test.js","@ember/-internals/runtime/tests/array/sortBy-test.js","@ember/-internals/runtime/tests/array/toArray-test.js","@ember/-internals/runtime/tests/array/uniq-test.js","@ember/-internals/runtime/tests/array/uniqBy-test.js","@ember/-internals/runtime/tests/array/without-test.js","@ember/-internals/runtime/tests/core/compare_test.js","@ember/-internals/runtime/tests/core/isEqual_test.js","@ember/-internals/runtime/tests/core/is_array_test.js","@ember/-internals/runtime/tests/core/is_empty_test.js","@ember/-internals/runtime/tests/core/type_of_test.js","@ember/-internals/runtime/tests/ext/rsvp_test.js","@ember/-internals/runtime/tests/helpers/array.js","@ember/-internals/runtime/tests/inject_test.js","@ember/-internals/runtime/tests/legacy_1x/mixins/observable/chained_test.js","@ember/-internals/runtime/tests/legacy_1x/mixins/observable/observable_test.js","@ember/-internals/runtime/tests/legacy_1x/system/object/base_test.js","@ember/-internals/runtime/tests/legacy_1x/system/object/concatenated_test.js","@ember/-internals/runtime/tests/mixins/array_test.js","@ember/-internals/runtime/tests/mixins/comparable_test.js","@ember/-internals/runtime/tests/mixins/container_proxy_test.js","@ember/-internals/runtime/tests/mixins/enumerable_test.js","@ember/-internals/runtime/tests/mixins/evented_test.js","@ember/-internals/runtime/tests/mixins/mutable_enumerable_test.js","@ember/-internals/runtime/tests/mixins/observable_test.js","@ember/-internals/runtime/tests/mixins/promise_proxy_test.js","@ember/-internals/runtime/tests/mixins/target_action_support_test.js","@ember/-internals/runtime/tests/mutable-array/addObject-test.js","@ember/-internals/runtime/tests/mutable-array/clear-test.js","@ember/-internals/runtime/tests/mutable-array/insertAt-test.js","@ember/-internals/runtime/tests/mutable-array/popObject-test.js","@ember/-internals/runtime/tests/mutable-array/pushObject-test.js","@ember/-internals/runtime/tests/mutable-array/pushObjects-test.js","@ember/-internals/runtime/tests/mutable-array/removeAt-test.js","@ember/-internals/runtime/tests/mutable-array/removeObject-test.js","@ember/-internals/runtime/tests/mutable-array/removeObjects-test.js","@ember/-internals/runtime/tests/mutable-array/replace-test.js","@ember/-internals/runtime/tests/mutable-array/reverseObjects-test.js","@ember/-internals/runtime/tests/mutable-array/setObjects-test.js","@ember/-internals/runtime/tests/mutable-array/shiftObject-test.js","@ember/-internals/runtime/tests/mutable-array/unshiftObject-test.js","@ember/-internals/runtime/tests/mutable-array/unshiftObjects-test.js","@ember/-internals/runtime/tests/system/array_proxy/arranged_content_test.js","@ember/-internals/runtime/tests/system/array_proxy/array_observer_test.js","@ember/-internals/runtime/tests/system/array_proxy/content_change_test.js","@ember/-internals/runtime/tests/system/array_proxy/length_test.js","@ember/-internals/runtime/tests/system/array_proxy/watching_and_listening_test.js","@ember/-internals/runtime/tests/system/core_object_test.js","@ember/-internals/runtime/tests/system/namespace/base_test.js","@ember/-internals/runtime/tests/system/native_array/a_test.js","@ember/-internals/runtime/tests/system/native_array/replace_test.js","@ember/-internals/runtime/tests/system/object/computed_test.js","@ember/-internals/runtime/tests/system/object/create_test.js","@ember/-internals/runtime/tests/system/object/destroy_test.js","@ember/-internals/runtime/tests/system/object/detectInstance_test.js","@ember/-internals/runtime/tests/system/object/detect_test.js","@ember/-internals/runtime/tests/system/object/es-compatibility-test.js","@ember/-internals/runtime/tests/system/object/events_test.js","@ember/-internals/runtime/tests/system/object/extend_test.js","@ember/-internals/runtime/tests/system/object/framework_test.js","@ember/-internals/runtime/tests/system/object/observer_test.js","@ember/-internals/runtime/tests/system/object/reopenClass_test.js","@ember/-internals/runtime/tests/system/object/reopen_test.js","@ember/-internals/runtime/tests/system/object/strict-mode-test.js","@ember/-internals/runtime/tests/system/object/toString_test.js","@ember/-internals/runtime/tests/system/object_proxy_test.js","@ember/-internals/utils/tests/cache_test.js","@ember/-internals/utils/tests/can_invoke_test.js","@ember/-internals/utils/tests/checkHasSuper_test.js","@ember/-internals/utils/tests/generate_guid_test.js","@ember/-internals/utils/tests/get-debug-name-test.js","@ember/-internals/utils/tests/guid_for_test.js","@ember/-internals/utils/tests/inspect_test.js","@ember/-internals/utils/tests/is_proxy_test.js","@ember/-internals/utils/tests/make_array_test.js","@ember/-internals/utils/tests/to-string-test.js","@ember/-internals/utils/tests/trackable-object-test.js","@ember/application/tests/application_instance_test.js","@ember/application/tests/application_test.js","@ember/application/tests/dependency_injection_test.js","@ember/application/tests/initializers_test.js","@ember/application/tests/instance_initializers_test.js","@ember/application/tests/lazy_load_test.js","@ember/application/tests/logging_test.js","@ember/application/tests/readiness_test.js","@ember/application/tests/reset_test.js","@ember/application/tests/visit_test.js","@ember/controller/tests/controller_test.js","@ember/debug/tests/handlers-test.js","@ember/debug/tests/main_test.js","@ember/engine/tests/engine_initializers_test.js","@ember/engine/tests/engine_instance_initializers_test.js","@ember/engine/tests/engine_instance_test.js","@ember/engine/tests/engine_parent_test.js","@ember/engine/tests/engine_test.js","@ember/error/tests/index_test.js","@ember/instrumentation/tests/index-test.js","@ember/object/tests/action_test.js","@ember/object/tests/computed/computed_macros_test.js","@ember/object/tests/computed/dependent-key-compat-test.js","@ember/object/tests/computed/macro_decorators_test.js","@ember/object/tests/computed/reduce_computed_macros_test.js","@ember/polyfills/tests/assign_test.js","@ember/runloop/tests/debounce_test.js","@ember/runloop/tests/later_test.js","@ember/runloop/tests/next_test.js","@ember/runloop/tests/once_test.js","@ember/runloop/tests/onerror_test.js","@ember/runloop/tests/run_bind_test.js","@ember/runloop/tests/run_test.js","@ember/runloop/tests/schedule_test.js","@ember/runloop/tests/unwind_test.js","@ember/service/tests/service_test.js","@ember/string/tests/camelize_test.js","@ember/string/tests/capitalize_test.js","@ember/string/tests/classify_test.js","@ember/string/tests/dasherize_test.js","@ember/string/tests/decamelize_test.js","@ember/string/tests/underscore_test.js","@ember/string/tests/w_test.js","ember-template-compiler/index.js","ember-template-compiler/lib/plugins/assert-against-attrs.js","ember-template-compiler/lib/plugins/assert-against-dynamic-helpers-modifiers.js","ember-template-compiler/lib/plugins/assert-against-named-blocks.js","ember-template-compiler/lib/plugins/assert-against-named-outlets.js","ember-template-compiler/lib/plugins/assert-input-helper-without-block.js","ember-template-compiler/lib/plugins/assert-reserved-named-arguments.js","ember-template-compiler/lib/plugins/assert-splattribute-expression.js","ember-template-compiler/lib/plugins/index.js","ember-template-compiler/lib/plugins/transform-action-syntax.js","ember-template-compiler/lib/plugins/transform-each-in-into-each.js","ember-template-compiler/lib/plugins/transform-each-track-array.js","ember-template-compiler/lib/plugins/transform-in-element.js","ember-template-compiler/lib/plugins/transform-quoted-bindings-into-just-bindings.js","ember-template-compiler/lib/plugins/transform-resolutions.js","ember-template-compiler/lib/plugins/transform-wrap-mount-and-outlet.js","ember-template-compiler/lib/plugins/utils.js","ember-template-compiler/lib/system/bootstrap.js","ember-template-compiler/lib/system/calculate-location-display.js","ember-template-compiler/lib/system/compile-options.js","ember-template-compiler/lib/system/compile.js","ember-template-compiler/lib/system/dasherize-component-name.js","ember-template-compiler/lib/system/initializer.js","ember-template-compiler/lib/system/precompile.js","ember-template-compiler/tests/basic-usage-test.js","ember-template-compiler/tests/plugins/assert-against-attrs-test.js","ember-template-compiler/tests/plugins/assert-against-named-blocks-test.js","ember-template-compiler/tests/plugins/assert-against-named-outlets-test.js","ember-template-compiler/tests/plugins/assert-input-helper-without-block-test.js","ember-template-compiler/tests/plugins/assert-reserved-named-arguments-test.js","ember-template-compiler/tests/plugins/assert-splattribute-expression-test.js","ember-template-compiler/tests/plugins/transform-component-invocation-test.js","ember-template-compiler/tests/plugins/transform-input-type-syntax-test.js","ember-template-compiler/tests/system/bootstrap-test.js","ember-template-compiler/tests/system/compile_options_test.js","ember-template-compiler/tests/system/dasherize-component-name-test.js","ember-template-compiler/tests/utils/transform-test-case.js","ember-testing/tests/adapters/adapter_test.js","ember-testing/tests/adapters/qunit_test.js","ember-testing/tests/adapters_test.js","ember-testing/tests/ext/rsvp_test.js","ember-testing/tests/helper_registration_test.js","ember-testing/tests/reexports_test.js","ember-testing/tests/test/waiters-test.js","ember/tests/application_lifecycle_test.js","ember/tests/component_context_test.js","ember/tests/component_registration_test.js","ember/tests/controller_test.js","ember/tests/ember-test-helpers-test.js","ember/tests/error_handler_test.js","ember/tests/homepage_example_test.js","ember/tests/integration/multiple-app-test.js","ember/tests/production_build_test.js","ember/tests/reexports_test.js","ember/tests/routing/decoupled_basic_test.js","ember/tests/routing/model_loading_test.js","ember/tests/routing/query_params_test.js","ember/tests/routing/query_params_test/model_dependent_state_with_query_params_test.js","ember/tests/routing/query_params_test/overlapping_query_params_test.js","ember/tests/routing/query_params_test/query_param_async_get_handler_test.js","ember/tests/routing/query_params_test/query_params_paramless_link_to_test.js","ember/tests/routing/query_params_test/shared_state_test.js","ember/tests/routing/router_map_test.js","ember/tests/routing/router_service_test/basic_test.js","ember/tests/routing/router_service_test/build_routeinfo_metadata_test.js","ember/tests/routing/router_service_test/currenturl_lifecycle_test.js","ember/tests/routing/router_service_test/events_test.js","ember/tests/routing/router_service_test/isActive_test.js","ember/tests/routing/router_service_test/non_application_test_test.js","ember/tests/routing/router_service_test/recognize_test.js","ember/tests/routing/router_service_test/refresh_test.js","ember/tests/routing/router_service_test/replaceWith_test.js","ember/tests/routing/router_service_test/transitionTo_test.js","ember/tests/routing/router_service_test/urlFor_test.js","ember/tests/routing/substates_test.js","ember/tests/routing/template_rendering_test.js","ember/tests/routing/toplevel_dom_test.js","ember/tests/service_injection_test.js","ember/tests/view_instrumentation_test.js","internal-test-helpers/index.js","internal-test-helpers/lib/apply-mixins.js","internal-test-helpers/lib/browser-detect.js","internal-test-helpers/lib/build-owner.js","internal-test-helpers/lib/compile.js","internal-test-helpers/lib/confirm-export.js","internal-test-helpers/lib/define-template-values.js","internal-test-helpers/lib/element-helpers.js","internal-test-helpers/lib/ember-dev/assertion.js","internal-test-helpers/lib/ember-dev/containers.js","internal-test-helpers/lib/ember-dev/debug.js","internal-test-helpers/lib/ember-dev/deprecation.js","internal-test-helpers/lib/ember-dev/method-call-tracker.js","internal-test-helpers/lib/ember-dev/namespaces.js","internal-test-helpers/lib/ember-dev/observers.js","internal-test-helpers/lib/ember-dev/run-loop.js","internal-test-helpers/lib/ember-dev/setup-qunit.js","internal-test-helpers/lib/ember-dev/utils.js","internal-test-helpers/lib/ember-dev/warning.js","internal-test-helpers/lib/equal-inner-html.js","internal-test-helpers/lib/equal-tokens.js","internal-test-helpers/lib/factory.js","internal-test-helpers/lib/get-all-property-names.js","internal-test-helpers/lib/get-text-of.js","internal-test-helpers/lib/matchers.js","internal-test-helpers/lib/module-for.js","internal-test-helpers/lib/node-query.js","internal-test-helpers/lib/registry-check.js","internal-test-helpers/lib/run.js","internal-test-helpers/lib/strip.js","internal-test-helpers/lib/system/synthetic-events.js","internal-test-helpers/lib/test-cases/abstract-application.js","internal-test-helpers/lib/test-cases/abstract.js","internal-test-helpers/lib/test-cases/application.js","internal-test-helpers/lib/test-cases/autoboot-application.js","internal-test-helpers/lib/test-cases/query-param.js","internal-test-helpers/lib/test-cases/rendering.js","internal-test-helpers/lib/test-cases/router-non-application.js","internal-test-helpers/lib/test-cases/router.js","internal-test-helpers/lib/test-cases/test-resolver-application.js","internal-test-helpers/lib/test-context.js","internal-test-helpers/lib/test-resolver.js","internal-test-helpers/tests/index-test.js"],"sourcesContent":["/*!\n * @overview Ember - JavaScript Application Framework\n * @copyright Copyright 2011-2021 Tilde Inc. and contributors\n * Portions Copyright 2006-2011 Strobe Inc.\n * Portions Copyright 2008-2011 Apple Inc. All rights reserved.\n * @license Licensed under MIT license\n * See https://raw.github.com/emberjs/ember.js/master/LICENSE\n * @version 4.1.0-alpha.2.mixonic-drop-export-of-built-ins+5d24ae74\n */\n","/* eslint-disable no-var */\n/* globals global globalThis self */\n/* eslint-disable-next-line no-unused-vars */\nvar define, require;\n\n(function () {\n var globalObj =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : null;\n\n if (globalObj === null) {\n throw new Error('unable to locate global object');\n }\n\n if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') {\n define = globalObj.define;\n require = globalObj.require;\n\n return;\n }\n\n var registry = Object.create(null);\n var seen = Object.create(null);\n\n function missingModule(name, referrerName) {\n if (referrerName) {\n throw new Error('Could not find module ' + name + ' required by: ' + referrerName);\n } else {\n throw new Error('Could not find module ' + name);\n }\n }\n\n function internalRequire(_name, referrerName) {\n var name = _name;\n var mod = registry[name];\n\n if (!mod) {\n name = name + '/index';\n mod = registry[name];\n }\n\n var exports = seen[name];\n\n if (exports !== undefined) {\n return exports;\n }\n\n exports = seen[name] = {};\n\n if (!mod) {\n missingModule(_name, referrerName);\n }\n\n var deps = mod.deps;\n var callback = mod.callback;\n var reified = new Array(deps.length);\n\n for (var i = 0; i < deps.length; i++) {\n if (deps[i] === 'exports') {\n reified[i] = exports;\n } else if (deps[i] === 'require') {\n reified[i] = require;\n } else {\n reified[i] = require(deps[i], name);\n }\n }\n\n callback.apply(this, reified);\n\n return exports;\n }\n\n require = function (name) {\n return internalRequire(name, null);\n };\n\n // eslint-disable-next-line no-unused-vars\n define = function (name, deps, callback) {\n registry[name] = { deps: deps, callback: callback };\n };\n\n // setup `require` module\n require['default'] = require;\n\n require.has = function registryHas(moduleName) {\n return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);\n };\n\n require._eak_seen = require.entries = registry;\n})();\n","define(\"@ember/-internals/container/tests/container_test\", [\"@ember/-internals/owner\", \"@ember/service\", \"@ember/-internals/container\", \"internal-test-helpers\"], function (_owner, _service, _container, _internalTestHelpers) {\n \"use strict\";\n\n (0, _internalTestHelpers.moduleFor)('Container.lookup', class extends _internalTestHelpers.AbstractTestCase {\n ['@test lookup returns a fresh instance if singleton: false is passed as an option'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n var postController1 = container.lookup('controller:post');\n var postController2 = container.lookup('controller:post', {\n singleton: false\n });\n var postController3 = container.lookup('controller:post', {\n singleton: false\n });\n var postController4 = container.lookup('controller:post');\n assert.equal(postController1.toString(), postController4.toString(), 'Singleton factories looked up normally return the same value');\n assert.notEqual(postController1.toString(), postController2.toString(), 'Singleton factories are not equal to factories looked up with singleton: false');\n assert.notEqual(postController2.toString(), postController3.toString(), 'Two factories looked up with singleton: false are not equal');\n assert.notEqual(postController3.toString(), postController4.toString(), 'A singleton factory looked up after a factory called with singleton: false is not equal');\n assert.ok(postController1 instanceof PostController, 'All instances are instances of the registered factory');\n assert.ok(postController2 instanceof PostController, 'All instances are instances of the registered factory');\n assert.ok(postController3 instanceof PostController, 'All instances are instances of the registered factory');\n assert.ok(postController4 instanceof PostController, 'All instances are instances of the registered factory');\n }\n\n ['@test lookup returns a fresh instance if singleton: false is passed as an option to lookup'](assert) {\n class TestFactory {\n constructor(opts) {\n Object.assign(this, opts);\n }\n\n static create(opts) {\n return new this(opts);\n }\n\n }\n\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('thing:test/obj', TestFactory);\n var instance1 = container.lookup('thing:test/obj');\n var instance2 = container.lookup('thing:test/obj', {\n singleton: false\n });\n var instance3 = container.lookup('thing:test/obj', {\n singleton: false\n });\n var instance4 = container.lookup('thing:test/obj');\n assert.ok(instance1 === instance4, 'factories looked up up without singleton: false are the same instance');\n assert.ok(instance1 !== instance2, 'factories looked up with singleton: false are a different instance');\n assert.ok(instance2 !== instance3, 'factories looked up with singleton: false are a different instance');\n assert.ok(instance3 !== instance4, 'factories looked up after a call to singleton: false is a different instance');\n assert.ok(instance1 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance2 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance3 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance4 instanceof TestFactory, 'All instances are instances of the registered factory');\n }\n\n ['@test lookup returns a fresh instance if singleton: false is passed as an option to register'](assert) {\n class TestFactory {\n constructor(opts) {\n Object.assign(this, opts);\n }\n\n static create(opts) {\n return new this(opts);\n }\n\n }\n\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('thing:test/obj', TestFactory, {\n singleton: false\n });\n var instance1 = container.lookup('thing:test/obj');\n var instance2 = container.lookup('thing:test/obj');\n var instance3 = container.lookup('thing:test/obj');\n assert.ok(instance1 !== instance2, 'each lookup is a different instance');\n assert.ok(instance2 !== instance3, 'each lookup is a different instance');\n assert.ok(instance1 !== instance3, 'each lookup is a different instance');\n assert.ok(instance1 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance2 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance3 instanceof TestFactory, 'All instances are instances of the registered factory');\n }\n\n ['@test lookup returns a singleton instance if singleton: true is passed as an option even if registered as singleton: false'](assert) {\n class TestFactory {\n constructor(opts) {\n Object.assign(this, opts);\n }\n\n static create(opts) {\n return new this(opts);\n }\n\n }\n\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('thing:test/obj', TestFactory, {\n singleton: false\n });\n var instance1 = container.lookup('thing:test/obj');\n var instance2 = container.lookup('thing:test/obj', {\n singleton: true\n });\n var instance3 = container.lookup('thing:test/obj', {\n singleton: true\n });\n var instance4 = container.lookup('thing:test/obj');\n assert.ok(instance1 !== instance2, 'each lookup is a different instance');\n assert.ok(instance2 === instance3, 'each singleton: true lookup is the same instance');\n assert.ok(instance3 !== instance4, 'each lookup is a different instance');\n assert.ok(instance1 !== instance4, 'each lookup is a different instance');\n assert.ok(instance1 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance2 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance3 instanceof TestFactory, 'All instances are instances of the registered factory');\n assert.ok(instance4 instanceof TestFactory, 'All instances are instances of the registered factory');\n }\n\n });\n (0, _internalTestHelpers.moduleFor)('Container', class extends _internalTestHelpers.AbstractTestCase {\n ['@test A registered factory returns the same instance each time'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n var postController = container.lookup('controller:post');\n assert.ok(postController instanceof PostController, 'The lookup is an instance of the factory');\n assert.equal(postController, container.lookup('controller:post'));\n }\n\n ['@test A non-singleton instance is never cached'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostView = (0, _internalTestHelpers.factory)();\n registry.register('view:post', PostView, {\n singleton: false\n });\n var postView1 = container.lookup('view:post');\n var postView2 = container.lookup('view:post');\n assert.ok(postView1 !== postView2, 'Non-singletons are not cached');\n }\n\n ['@test A non-instantiated property is not instantiated'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n\n var template = function () {};\n\n registry.register('template:foo', template, {\n instantiate: false\n });\n assert.equal(container.lookup('template:foo'), template);\n }\n\n ['@test A failed lookup returns undefined'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n assert.equal(container.lookup('doesnot:exist'), undefined);\n }\n\n ['@test An invalid factory throws an error']() {\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('controller:foo', {});\n expectAssertion(() => {\n container.lookup('controller:foo');\n }, /Failed to create an instance of 'controller:foo'/);\n }\n\n ['@test The container returns same value each time even if the value is falsey'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('falsy:value', null, {\n instantiate: false\n });\n assert.strictEqual(container.lookup('falsy:value'), container.lookup('falsy:value'));\n }\n\n ['@test The container can use a registry hook to resolve factories lazily'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.resolver = {\n resolve(fullName) {\n if (fullName === 'controller:post') {\n return PostController;\n }\n }\n\n };\n var postController = container.lookup('controller:post');\n assert.ok(postController instanceof PostController, 'The correct factory was provided');\n }\n\n ['@test The container normalizes names before resolving'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n\n registry.normalizeFullName = function () {\n return 'controller:post';\n };\n\n registry.register('controller:post', PostController);\n var postController = container.lookup('controller:normalized');\n assert.ok(postController instanceof PostController, 'Normalizes the name before resolving');\n }\n\n ['@test The container normalizes names when looking factory up'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n\n registry.normalizeFullName = function () {\n return 'controller:post';\n };\n\n registry.register('controller:post', PostController);\n var fact = container.factoryFor('controller:normalized');\n var factInstance = fact.create();\n assert.ok(factInstance instanceof PostController, 'Normalizes the name');\n }\n\n ['@test Options can be registered that should be applied to a given factory'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostView = (0, _internalTestHelpers.factory)();\n registry.resolver = {\n resolve(fullName) {\n if (fullName === 'view:post') {\n return PostView;\n }\n }\n\n };\n registry.options('view:post', {\n instantiate: true,\n singleton: false\n });\n var postView1 = container.lookup('view:post');\n var postView2 = container.lookup('view:post');\n assert.ok(postView1 instanceof PostView, 'The correct factory was provided');\n assert.ok(postView2 instanceof PostView, 'The correct factory was provided');\n assert.ok(postView1 !== postView2, 'The two lookups are different');\n }\n\n ['@test Options can be registered that should be applied to all factories for a given type'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostView = (0, _internalTestHelpers.factory)();\n registry.resolver = {\n resolve(fullName) {\n if (fullName === 'view:post') {\n return PostView;\n }\n }\n\n };\n registry.optionsForType('view', {\n singleton: false\n });\n var postView1 = container.lookup('view:post');\n var postView2 = container.lookup('view:post');\n assert.ok(postView1 instanceof PostView, 'The correct factory was provided');\n assert.ok(postView2 instanceof PostView, 'The correct factory was provided');\n assert.ok(postView1 !== postView2, 'The two lookups are different');\n }\n\n ['@test Factory resolves are cached'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n var resolveWasCalled = [];\n\n registry.resolve = function (fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n };\n\n assert.deepEqual(resolveWasCalled, []);\n container.factoryFor('controller:post');\n assert.deepEqual(resolveWasCalled, ['controller:post']);\n container.factoryFor('controller:post');\n assert.deepEqual(resolveWasCalled, ['controller:post']);\n }\n\n ['@test factory for non extendables (MODEL) resolves are cached'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = (0, _internalTestHelpers.factory)();\n var resolveWasCalled = [];\n\n registry.resolve = function (fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n };\n\n assert.deepEqual(resolveWasCalled, []);\n container.factoryFor('model:post');\n assert.deepEqual(resolveWasCalled, ['model:post']);\n container.factoryFor('model:post');\n assert.deepEqual(resolveWasCalled, ['model:post']);\n }\n\n ['@test factory for non extendables resolves are cached'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var PostController = {};\n var resolveWasCalled = [];\n\n registry.resolve = function (fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n };\n\n assert.deepEqual(resolveWasCalled, []);\n container.factoryFor('foo:post');\n assert.deepEqual(resolveWasCalled, ['foo:post']);\n container.factoryFor('foo:post');\n assert.deepEqual(resolveWasCalled, ['foo:post']);\n }\n\n [`@test A factory's lazy injections are validated when first instantiated`]() {\n var registry = new _container.Registry();\n var container = registry.container();\n var Apple = (0, _internalTestHelpers.factory)();\n var Orange = (0, _internalTestHelpers.factory)();\n Apple.reopenClass({\n _lazyInjections() {\n return [{\n specifier: 'orange:main'\n }, {\n specifier: 'banana:main'\n }];\n }\n\n });\n registry.register('apple:main', Apple);\n registry.register('orange:main', Orange);\n expectAssertion(() => {\n container.lookup('apple:main');\n }, /Attempting to inject an unknown injection: 'banana:main'/);\n }\n\n ['@test Lazy injection validations are cached'](assert) {\n if (!true\n /* DEBUG */\n ) {\n assert.expect(0);\n return;\n }\n\n assert.expect(1);\n var registry = new _container.Registry();\n var container = registry.container();\n var Apple = (0, _internalTestHelpers.factory)();\n var Orange = (0, _internalTestHelpers.factory)();\n Apple.reopenClass({\n _lazyInjections: () => {\n assert.ok(true, 'should call lazy injection method');\n return [{\n specifier: 'orange:main'\n }];\n }\n });\n registry.register('apple:main', Apple);\n registry.register('orange:main', Orange);\n container.lookup('apple:main');\n container.lookup('apple:main');\n }\n\n ['@test An object with its owner pre-set should be returned from ownerInjection'](assert) {\n var owner = {};\n var registry = new _container.Registry();\n var container = registry.container({\n owner\n });\n var result = container.ownerInjection();\n assert.equal((0, _owner.getOwner)(result), owner, 'owner is properly included');\n }\n\n ['@test ownerInjection should be usable to create a service for testing'](assert) {\n assert.expect(0);\n var owner = {};\n var registry = new _container.Registry();\n var container = registry.container({\n owner\n });\n var result = container.ownerInjection();\n\n _service.default.create(result);\n }\n\n ['@test #factoryFor class is registered class'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n var factoryManager = container.factoryFor('component:foo-bar');\n assert.deepEqual(factoryManager.class, Component, 'No double extend');\n }\n\n ['@test #factoryFor must supply a fullname']() {\n var registry = new _container.Registry();\n var container = registry.container();\n expectAssertion(() => {\n container.factoryFor('chad-bar');\n }, /fullName must be a proper full name/);\n }\n\n ['@test #factoryFor returns a factory manager'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n var factoryManager = container.factoryFor('component:foo-bar');\n assert.ok(factoryManager.create);\n assert.ok(factoryManager.class);\n }\n\n ['@test #factoryFor returns a cached factory manager for the same type'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n registry.register('component:baz-bar', Component);\n var factoryManager1 = container.factoryFor('component:foo-bar');\n var factoryManager2 = container.factoryFor('component:foo-bar');\n var factoryManager3 = container.factoryFor('component:baz-bar');\n assert.equal(factoryManager1, factoryManager2, 'cache hit');\n assert.notEqual(factoryManager1, factoryManager3, 'cache miss');\n }\n\n ['@test #factoryFor class returns the factory function'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n var factoryManager = container.factoryFor('component:foo-bar');\n assert.deepEqual(factoryManager.class, Component, 'No double extend');\n }\n\n ['@test #factoryFor instance have a common parent'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n var factoryManager1 = container.factoryFor('component:foo-bar');\n var factoryManager2 = container.factoryFor('component:foo-bar');\n var instance1 = factoryManager1.create({\n foo: 'foo'\n });\n var instance2 = factoryManager2.create({\n bar: 'bar'\n });\n assert.deepEqual(instance1.constructor, instance2.constructor);\n }\n\n ['@test can properly reset cache'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var Component = (0, _internalTestHelpers.factory)();\n registry.register('component:foo-bar', Component);\n var factory1 = container.factoryFor('component:foo-bar');\n var factory2 = container.factoryFor('component:foo-bar');\n var instance1 = container.lookup('component:foo-bar');\n var instance2 = container.lookup('component:foo-bar');\n assert.equal(instance1, instance2);\n assert.equal(factory1, factory2);\n container.reset();\n var factory3 = container.factoryFor('component:foo-bar');\n var instance3 = container.lookup('component:foo-bar');\n assert.notEqual(instance1, instance3);\n assert.notEqual(factory1, factory3);\n }\n\n [`@test assert when calling lookup after destroy on a container`](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('service:foo', (0, _internalTestHelpers.factory)());\n var instance = container.lookup('service:foo');\n assert.ok(instance, 'precond lookup successful');\n (0, _internalTestHelpers.runTask)(() => {\n container.destroy();\n container.finalizeDestroy();\n });\n assert.throws(() => {\n container.lookup('service:foo');\n }, /Can not call `.lookup` after the owner has been destroyed/);\n }\n\n [`@test assert when calling factoryFor after destroy on a container`](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('service:foo', (0, _internalTestHelpers.factory)());\n var instance = container.lookup('service:foo');\n assert.ok(instance, 'precond lookup successful');\n (0, _internalTestHelpers.runTask)(() => {\n container.destroy();\n container.finalizeDestroy();\n });\n assert.throws(() => {\n container.factoryFor('service:foo');\n }, /Can not call `.factoryFor` after the owner has been destroyed/);\n } // this is skipped until templates and the glimmer environment do not require `OWNER` to be\n // passed in as constructor args\n\n\n ['@skip #factoryFor does not add properties to the object being instantiated'](assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n\n class Component {\n static create(options) {\n var instance = new this();\n Object.assign(instance, options);\n return instance;\n }\n\n }\n\n registry.register('component:foo-bar', Component);\n var componentFactory = container.factoryFor('component:foo-bar');\n var instance = componentFactory.create(); // note: _guid and isDestroyed are being set in the `factory` constructor\n // not via registry/container shenanigans\n\n assert.deepEqual(Object.keys(instance), []);\n }\n\n '@test instantiating via container.lookup during destruction enqueues destruction'(assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n var otherInstance;\n\n class Service extends (0, _internalTestHelpers.factory)() {\n destroy() {\n otherInstance = container.lookup('service:other');\n assert.ok(otherInstance.isDestroyed, 'service:other was destroyed');\n }\n\n }\n\n registry.register('service:foo', Service);\n registry.register('service:other', (0, _internalTestHelpers.factory)());\n var instance = container.lookup('service:foo');\n assert.ok(instance, 'precond lookup successful');\n (0, _internalTestHelpers.runTask)(() => {\n container.destroy();\n container.finalizeDestroy();\n });\n }\n\n '@test instantiating via container.factoryFor().create() after destruction throws an error'(assert) {\n var registry = new _container.Registry();\n var container = registry.container();\n registry.register('service:foo', (0, _internalTestHelpers.factory)());\n registry.register('service:other', (0, _internalTestHelpers.factory)());\n var Factory = container.factoryFor('service:other');\n (0, _internalTestHelpers.runTask)(() => {\n container.destroy();\n container.finalizeDestroy();\n });\n assert.throws(() => {\n Factory.create();\n }, /Can not create new instances after the owner has been destroyed \\(you attempted to create service:other\\)/);\n }\n\n });\n});","define(\"@ember/-internals/container/tests/owner_test\", [\"@ember/-internals/owner\", \"internal-test-helpers\"], function (_owner, _internalTestHelpers) {\n \"use strict\";\n\n (0, _internalTestHelpers.moduleFor)('Owner', class extends _internalTestHelpers.AbstractTestCase {\n ['@test An owner can be set with `setOwner` and retrieved with `getOwner`'](assert) {\n var owner = {};\n var obj = {};\n assert.strictEqual((0, _owner.getOwner)(obj), undefined, 'owner has not been set');\n (0, _owner.setOwner)(obj, owner);\n assert.strictEqual((0, _owner.getOwner)(obj), owner, 'owner has been set');\n }\n\n });\n});","define(\"@ember/-internals/container/tests/registry_test\", [\"@ember/-internals/container\", \"internal-test-helpers\"], function (_container, _internalTestHelpers) {\n \"use strict\";\n\n (0, _internalTestHelpers.moduleFor)('Registry', class extends _internalTestHelpers.AbstractTestCase {\n ['@test A registered factory is returned from resolve'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n var PostControllerFactory = registry.resolve('controller:post');\n assert.ok(PostControllerFactory, 'factory is returned');\n assert.ok(PostControllerFactory.create() instanceof PostController, 'The return of factory.create is an instance of PostController');\n }\n\n ['@test The registered factory returned from resolve is the same factory each time'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n assert.deepEqual(registry.resolve('controller:post'), registry.resolve('controller:post'), 'The return of resolve is always the same');\n }\n\n ['@test The registered value returned from resolve is the same value each time even if the value is falsy'](assert) {\n var registry = new _container.Registry();\n registry.register('falsy:value', null, {\n instantiate: false\n });\n assert.strictEqual(registry.resolve('falsy:value'), registry.resolve('falsy:value'), 'The return of resolve is always the same');\n }\n\n ['@test The value returned from resolver is the same value as the original value even if the value is falsy'](assert) {\n var resolver = {\n resolve(fullName) {\n if (fullName === 'falsy:value') {\n return null;\n }\n }\n\n };\n var registry = new _container.Registry({\n resolver\n });\n assert.strictEqual(registry.resolve('falsy:value'), null);\n }\n\n ['@test A registered factory returns true for `has` if an item is registered'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n assert.equal(registry.has('controller:post'), true, 'The `has` method returned true for registered factories');\n assert.equal(registry.has('controller:posts'), false, 'The `has` method returned false for unregistered factories');\n }\n\n ['@test The registry can take a hook to resolve factories lazily'](assert) {\n var PostController = (0, _internalTestHelpers.factory)();\n var resolver = {\n resolve(fullName) {\n if (fullName === 'controller:post') {\n return PostController;\n }\n }\n\n };\n var registry = new _container.Registry({\n resolver\n });\n assert.strictEqual(registry.resolve('controller:post'), PostController, 'The correct factory was provided');\n }\n\n ['@test The registry respects the resolver hook for `has`'](assert) {\n var PostController = (0, _internalTestHelpers.factory)();\n var resolver = {\n resolve(fullName) {\n if (fullName === 'controller:post') {\n return PostController;\n }\n }\n\n };\n var registry = new _container.Registry({\n resolver\n });\n assert.ok(registry.has('controller:post'), 'the `has` method uses the resolver hook');\n }\n\n ['@test The registry normalizes names when resolving'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n\n registry.normalizeFullName = function () {\n return 'controller:post';\n };\n\n registry.register('controller:post', PostController);\n var type = registry.resolve('controller:normalized');\n assert.strictEqual(type, PostController, 'Normalizes the name when resolving');\n }\n\n ['@test The registry normalizes names when checking if the factory is registered'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n\n registry.normalizeFullName = function (fullName) {\n return fullName === 'controller:normalized' ? 'controller:post' : fullName;\n };\n\n registry.register('controller:post', PostController);\n var isPresent = registry.has('controller:normalized');\n assert.equal(isPresent, true, 'Normalizes the name when checking if the factory or instance is present');\n }\n\n ['@test cannot register an `undefined` factory']() {\n var registry = new _container.Registry();\n expectAssertion(() => {\n registry.register('controller:apple', undefined);\n }, '');\n }\n\n ['@test can re-register a factory'](assert) {\n var registry = new _container.Registry();\n var FirstApple = (0, _internalTestHelpers.factory)('first');\n var SecondApple = (0, _internalTestHelpers.factory)('second');\n registry.register('controller:apple', FirstApple);\n registry.register('controller:apple', SecondApple);\n assert.ok(registry.resolve('controller:apple').create() instanceof SecondApple);\n }\n\n ['@test cannot re-register a factory if it has been resolved'](assert) {\n var registry = new _container.Registry();\n var FirstApple = (0, _internalTestHelpers.factory)('first');\n var SecondApple = (0, _internalTestHelpers.factory)('second');\n registry.register('controller:apple', FirstApple);\n assert.strictEqual(registry.resolve('controller:apple'), FirstApple);\n expectAssertion(function () {\n registry.register('controller:apple', SecondApple);\n }, /Cannot re-register: 'controller:apple', as it has already been resolved\\./);\n assert.strictEqual(registry.resolve('controller:apple'), FirstApple);\n }\n\n ['@test registry.has should not error for invalid fullNames'](assert) {\n var registry = new _container.Registry();\n assert.ok(!registry.has('foo:bar:baz'));\n }\n\n ['@test once resolved, always return the same result'](assert) {\n var registry = new _container.Registry();\n registry.resolver = {\n resolve() {\n return 'bar';\n }\n\n };\n var Bar = registry.resolve('models:bar');\n registry.resolver = {\n resolve() {\n return 'not bar';\n }\n\n };\n assert.equal(registry.resolve('models:bar'), Bar);\n }\n\n ['@test factory resolves are cached'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n var resolveWasCalled = [];\n registry.resolver = {\n resolve(fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n }\n\n };\n assert.deepEqual(resolveWasCalled, []);\n registry.resolve('controller:post');\n assert.deepEqual(resolveWasCalled, ['controller:post']);\n registry.resolve('controller:post');\n assert.deepEqual(resolveWasCalled, ['controller:post']);\n }\n\n ['@test factory for non extendables (MODEL) resolves are cached'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n var resolveWasCalled = [];\n registry.resolver = {\n resolve(fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n }\n\n };\n assert.deepEqual(resolveWasCalled, []);\n registry.resolve('model:post');\n assert.deepEqual(resolveWasCalled, ['model:post']);\n registry.resolve('model:post');\n assert.deepEqual(resolveWasCalled, ['model:post']);\n }\n\n ['@test factory for non extendables resolves are cached'](assert) {\n var registry = new _container.Registry();\n var PostController = {};\n var resolveWasCalled = [];\n registry.resolver = {\n resolve(fullName) {\n resolveWasCalled.push(fullName);\n return PostController;\n }\n\n };\n assert.deepEqual(resolveWasCalled, []);\n registry.resolve('foo:post');\n assert.deepEqual(resolveWasCalled, ['foo:post']);\n registry.resolve('foo:post');\n assert.deepEqual(resolveWasCalled, ['foo:post']);\n }\n\n ['@test registry.container creates a container'](assert) {\n var registry = new _container.Registry();\n var PostController = (0, _internalTestHelpers.factory)();\n registry.register('controller:post', PostController);\n var container = registry.container();\n var postController = container.lookup('controller:post');\n assert.ok(postController instanceof PostController, 'The lookup is an instance of the registered factory');\n }\n\n ['@test `describe` will be handled by the resolver, then by the fallback registry, if available'](assert) {\n var fallback = {\n describe(fullName) {\n return `${fullName}-fallback`;\n }\n\n };\n var resolver = {\n lookupDescription(fullName) {\n return `${fullName}-resolver`;\n }\n\n };\n var registry = new _container.Registry({\n fallback,\n resolver\n });\n assert.equal(registry.describe('controller:post'), 'controller:post-resolver', '`describe` handled by the resolver first.');\n registry.resolver = null;\n assert.equal(registry.describe('controller:post'), 'controller:post-fallback', '`describe` handled by fallback registry next.');\n registry.fallback = null;\n assert.equal(registry.describe('controller:post'), 'controller:post', '`describe` by default returns argument.');\n }\n\n ['@test `normalizeFullName` will be handled by the resolver, then by the fallback registry, if available'](assert) {\n var fallback = {\n normalizeFullName(fullName) {\n return `${fullName}-fallback`;\n }\n\n };\n var resolver = {\n normalize(fullName) {\n return `${fullName}-resolver`;\n }\n\n };\n var registry = new _container.Registry({\n fallback,\n resolver\n });\n assert.equal(registry.normalizeFullName('controller:post'), 'controller:post-resolver', '`normalizeFullName` handled by the resolver first.');\n registry.resolver = null;\n assert.equal(registry.normalizeFullName('controller:post'), 'controller:post-fallback', '`normalizeFullName` handled by fallback registry next.');\n registry.fallback = null;\n assert.equal(registry.normalizeFullName('controller:post'), 'controller:post', '`normalizeFullName` by default returns argument.');\n }\n\n ['@test `makeToString` will be handled by the resolver, then by the fallback registry, if available'](assert) {\n var fallback = {\n makeToString(fullName) {\n return `${fullName}-fallback`;\n }\n\n };\n var resolver = {\n makeToString(fullName) {\n return `${fullName}-resolver`;\n }\n\n };\n var registry = new _container.Registry({\n fallback,\n resolver\n });\n assert.equal(registry.makeToString('controller:post'), 'controller:post-resolver', '`makeToString` handled by the resolver first.');\n registry.resolver = null;\n assert.equal(registry.makeToString('controller:post'), 'controller:post-fallback', '`makeToString` handled by fallback registry next.');\n registry.fallback = null;\n assert.equal(registry.makeToString('controller:post'), 'controller:post', '`makeToString` by default returns argument.');\n }\n\n ['@test `resolve` can be handled by a fallback registry'](assert) {\n var fallback = new _container.Registry();\n var registry = new _container.Registry({\n fallback: fallback\n });\n var PostController = (0, _internalTestHelpers.factory)();\n fallback.register('controller:post', PostController);\n var PostControllerFactory = registry.resolve('controller:post');\n assert.ok(PostControllerFactory, 'factory is returned');\n assert.ok(PostControllerFactory.create() instanceof PostController, 'The return of factory.create is an instance of PostController');\n }\n\n ['@test `has` can be handled by a fallback registry'](assert) {\n var fallback = new _container.Registry();\n var registry = new _container.Registry({\n fallback: fallback\n });\n var PostController = (0, _internalTestHelpers.factory)();\n fallback.register('controller:post', PostController);\n assert.equal(registry.has('controller:post'), true, 'Fallback registry is checked for registration');\n }\n\n ['@test `knownForType` contains keys for each item of a given type'](assert) {\n var registry = new _container.Registry();\n registry.register('foo:bar-baz', 'baz');\n registry.register('foo:qux-fez', 'fez');\n var found = registry.knownForType('foo');\n assert.deepEqual(found, {\n 'foo:bar-baz': true,\n 'foo:qux-fez': true\n });\n }\n\n ['@test `knownForType` includes fallback registry results'](assert) {\n var fallback = new _container.Registry();\n var registry = new _container.Registry({\n fallback: fallback\n });\n registry.register('foo:bar-baz', 'baz');\n registry.register('foo:qux-fez', 'fez');\n fallback.register('foo:zurp-zorp', 'zorp');\n var found = registry.knownForType('foo');\n assert.deepEqual(found, {\n 'foo:bar-baz': true,\n 'foo:qux-fez': true,\n 'foo:zurp-zorp': true\n });\n }\n\n ['@test `knownForType` is called on the resolver if present'](assert) {\n assert.expect(3);\n var resolver = {\n knownForType(type) {\n assert.ok(true, 'knownForType called on the resolver');\n assert.equal(type, 'foo', 'the type was passed through');\n return {\n 'foo:yorp': true\n };\n }\n\n };\n var registry = new _container.Registry({\n resolver\n });\n registry.register('foo:bar-baz', 'baz');\n var found = registry.knownForType('foo');\n assert.deepEqual(found, {\n 'foo:yorp': true,\n 'foo:bar-baz': true\n });\n }\n\n });\n (0, _internalTestHelpers.moduleFor)('Registry privatize', class extends _internalTestHelpers.AbstractTestCase {\n ['@test valid format'](assert) {\n var privatized = (0, _container.privatize)(['secret:factory']);\n var matched = privatized.match(/^([^:]+):([^:]+)-(\\d+)$/);\n assert.ok(matched, 'privatized format was recognized');\n assert.equal(matched[1], 'secret');\n assert.equal(matched[2], 'factory');\n assert.ok(/^\\d+$/.test(matched[3]));\n }\n\n });\n});","define(\"@ember/-internals/extension-support/tests/container_debug_adapter_test\", [\"internal-test-helpers\", \"@ember/runloop\", \"@ember/controller\", \"@ember/-internals/extension-support/index\", \"@ember/debug\"], function (_internalTestHelpers, _runloop, _controller, _index, _debug) {\n \"use strict\";\n\n // Must be required to export Ember.ContainerDebugAdapter.\n var originalDebug = (0, _debug.getDebugFunction)('debug');\n (0, _internalTestHelpers.moduleFor)('Container Debug Adapter', class extends _internalTestHelpers.ApplicationTestCase {\n constructor() {\n (0, _debug.setDebugFunction)('debug', () => {});\n super();\n this.adapter = this.application.__deprecatedInstance__.lookup('container-debug-adapter:main');\n }\n\n get applicationOptions() {\n return Object.assign(super.applicationOptions, {\n autoboot: true\n });\n }\n\n teardown() {\n (0, _debug.setDebugFunction)('debug', originalDebug);\n (0, _runloop.run)(() => {\n this.adapter.destroy();\n });\n super.teardown();\n }\n\n ['@test default ContainerDebugAdapter cannot catalog certain entries by type'](assert) {\n assert.equal(this.adapter.canCatalogEntriesByType('model'), false, 'canCatalogEntriesByType should return false for model');\n assert.equal(this.adapter.canCatalogEntriesByType('template'), false, 'canCatalogEntriesByType should return false for template');\n }\n\n ['@test default ContainerDebugAdapter can catalog typical entries by type'](assert) {\n assert.equal(this.adapter.canCatalogEntriesByType('controller'), true, 'canCatalogEntriesByType should return true for controller');\n assert.equal(this.adapter.canCatalogEntriesByType('route'), true, 'canCatalogEntriesByType should return true for route');\n assert.equal(this.adapter.canCatalogEntriesByType('view'), true, 'canCatalogEntriesByType should return true for view');\n }\n\n ['@test default ContainerDebugAdapter catalogs controller entries'](assert) {\n this.application.PostController = _controller.default.extend();\n var controllerClasses = this.adapter.catalogEntriesByType('controller');\n assert.equal(controllerClasses.length, 1, 'found 1 class');\n assert.equal(controllerClasses[0], 'post', 'found the right class');\n }\n\n });\n});","define(\"@ember/-internals/extension-support/tests/data_adapter_test\", [\"@ember/runloop\", \"@ember/-internals/metal\", \"@ember/-internals/runtime\", \"@ember/-internals/extension-support/lib/data_adapter\", \"internal-test-helpers\"], function (_runloop, _metal, _runtime, _data_adapter, _internalTestHelpers) {\n \"use strict\";\n\n var adapter;\n\n var Model = _runtime.Object.extend();\n\n var PostClass = Model.extend();\n\n var DataAdapter = _data_adapter.default.extend({\n detect(klass) {\n return klass !== Model && Model.detect(klass);\n },\n\n init() {\n this._super(...arguments);\n\n this.set('containerDebugAdapter', {\n canCatalogEntriesByType() {\n return true;\n },\n\n catalogEntriesByType() {\n return (0, _runtime.A)(['post']);\n }\n\n });\n }\n\n });\n\n (0, _internalTestHelpers.moduleFor)('Data Adapter', class extends _internalTestHelpers.ApplicationTestCase {\n teardown() {\n super.teardown();\n adapter = undefined;\n }\n\n ['@test Model types added'](assert) {\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords() {\n return (0, _runtime.A)([1, 2, 3]);\n },\n\n columnsForType() {\n return [{\n name: 'title',\n desc: 'Title'\n }];\n }\n\n }));\n this.add('model:post', PostClass);\n return this.visit('/').then(() => {\n var adapter = this.applicationInstance.lookup('data-adapter:main');\n\n function modelTypesAdded(types) {\n assert.equal(types.length, 1);\n var postType = types[0];\n assert.equal(postType.name, 'post', 'Correctly sets the name');\n assert.equal(postType.count, 3, 'Correctly sets the record count');\n assert.strictEqual(postType.object, PostClass, 'Correctly sets the object');\n assert.deepEqual(postType.columns, [{\n name: 'title',\n desc: 'Title'\n }], 'Correctly sets the columns');\n }\n\n adapter.watchModelTypes(modelTypesAdded);\n });\n }\n\n ['@test getRecords gets a model name as second argument'](assert) {\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords(klass, name) {\n assert.equal(name, 'post');\n return (0, _runtime.A)();\n }\n\n }));\n this.add('model:post', PostClass);\n return this.visit('/').then(() => {\n adapter = this.applicationInstance.lookup('data-adapter:main');\n adapter.watchModelTypes(function () {});\n });\n }\n\n ['@test Model types added with custom container-debug-adapter'](assert) {\n var StubContainerDebugAdapter = _runtime.Object.extend({\n canCatalogEntriesByType() {\n return true;\n },\n\n catalogEntriesByType() {\n return (0, _runtime.A)(['post']);\n }\n\n });\n\n this.add('container-debug-adapter:main', StubContainerDebugAdapter);\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords() {\n return (0, _runtime.A)([1, 2, 3]);\n },\n\n columnsForType() {\n return [{\n name: 'title',\n desc: 'Title'\n }];\n }\n\n }));\n this.add('model:post', PostClass);\n return this.visit('/').then(() => {\n var adapter = this.applicationInstance.lookup('data-adapter:main');\n\n function modelTypesAdded(types) {\n assert.equal(types.length, 1);\n var postType = types[0];\n assert.equal(postType.name, 'post', 'Correctly sets the name');\n assert.equal(postType.count, 3, 'Correctly sets the record count');\n assert.strictEqual(postType.object, PostClass, 'Correctly sets the object');\n assert.deepEqual(postType.columns, [{\n name: 'title',\n desc: 'Title'\n }], 'Correctly sets the columns');\n }\n\n adapter.watchModelTypes(modelTypesAdded);\n });\n }\n\n ['@test Model Types Updated'](assert) {\n var records = (0, _runtime.A)([1, 2, 3]);\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords() {\n return records;\n }\n\n }));\n this.add('model:post', PostClass);\n return this.visit('/').then(() => {\n adapter = this.applicationInstance.lookup('data-adapter:main');\n\n function modelTypesAdded() {\n (0, _runloop.run)(() => {\n records.pushObject(4);\n });\n }\n\n function modelTypesUpdated(types) {\n var postType = types[0];\n assert.equal(postType.count, 4, 'Correctly updates the count');\n }\n\n adapter.watchModelTypes(modelTypesAdded, modelTypesUpdated);\n });\n }\n\n ['@test Records Added'](assert) {\n var countAdded = 1;\n var post = PostClass.create();\n var recordList = (0, _runtime.A)([post]);\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords() {\n return recordList;\n },\n\n getRecordColor() {\n return 'blue';\n },\n\n getRecordColumnValues() {\n return {\n title: 'Post ' + countAdded\n };\n },\n\n getRecordKeywords() {\n return ['Post ' + countAdded];\n }\n\n }));\n this.add('model:post', PostClass);\n return this.visit('/').then(() => {\n adapter = this.applicationInstance.lookup('data-adapter:main');\n\n function recordsAdded(records) {\n var record = records[0];\n assert.equal(record.color, 'blue', 'Sets the color correctly');\n assert.deepEqual(record.columnValues, {\n title: 'Post ' + countAdded\n }, 'Sets the column values correctly');\n assert.deepEqual(record.searchKeywords, ['Post ' + countAdded], 'Sets search keywords correctly');\n assert.strictEqual(record.object, post, 'Sets the object to the record instance');\n }\n\n adapter.watchRecords('post', recordsAdded);\n countAdded++;\n post = PostClass.create();\n recordList.pushObject(post);\n });\n }\n\n ['@test Observes and releases a record correctly'](assert) {\n var updatesCalled = 0;\n var post = PostClass.create({\n title: 'Post'\n });\n var recordList = (0, _runtime.A)([post]);\n this.add('data-adapter:main', DataAdapter.extend({\n getRecords() {\n return recordList;\n },\n\n getRecordColumnValues(record) {\n return {\n title: (0, _metal.get)(record, 'title')\n };\n }\n\n }));\n this.add('model:post', PostClass);\n var release;\n return this.visit('/').then(() => {\n adapter = this.applicationInstance.lookup('data-adapter:main');\n\n function recordsAdded(records) {\n assert.equal(records[0].columnValues.title, 'Post', 'Post added correctly');\n }\n\n function recordsUpdated(records) {\n updatesCalled++;\n assert.equal(records[0].columnValues.title, 'Post Modified');\n }\n\n release = adapter.watchRecords('post', recordsAdded, recordsUpdated);\n return (0, _internalTestHelpers.runLoopSettled)();\n }).then(() => {\n (0, _metal.set)(post, 'title', 'Post Modified');\n return (0, _internalTestHelpers.runLoopSettled)();\n }).then(() => {\n release();\n (0, _metal.set)(post, 'title', 'New Title');\n assert.equal(updatesCalled, 1, 'Release function removes observers');\n });\n }\n\n ['@test _nameToClass does not error when not found'](assert) {\n this.add('data-adapter:main', DataAdapter);\n return this.visit('/').then(() => {\n adapter = this.applicationInstance.lookup('data-adapter:main');\n\n var klass = adapter._nameToClass('foo');\n\n assert.equal(klass, undefined, 'returns undefined');\n });\n }\n\n });\n});","define(\"@ember/-internals/glimmer/tests/integration/application/actions-test\", [\"internal-test-helpers\", \"@ember/controller\", \"@ember/debug\", \"@ember/-internals/glimmer/tests/utils/helpers\"], function (_internalTestHelpers, _controller, _debug, _helpers) {\n \"use strict\";\n\n var originalDebug = (0, _debug.getDebugFunction)('debug');\n\n var noop = function () {};\n\n (0, _internalTestHelpers.moduleFor)('Application test: actions', class extends _internalTestHelpers.ApplicationTestCase {\n constructor() {\n (0, _debug.setDebugFunction)('debug', noop);\n super(...arguments);\n }\n\n teardown() {\n (0, _debug.setDebugFunction)('debug', originalDebug);\n }\n\n ['@test actions in top level template application template target application controller'](assert) {\n assert.expect(1);\n this.add('controller:application', _controller.default.extend({\n actions: {\n handleIt() {\n assert.ok(true, 'controller received action properly');\n }\n\n }\n }));\n this.addTemplate('application', '');\n return this.visit('/').then(() => {\n (0, _internalTestHelpers.runTask)(() => this.$('#handle-it').click());\n });\n }\n\n ['@test actions in nested outlet template target their controller'](assert) {\n assert.expect(1);\n this.add('controller:application', _controller.default.extend({\n actions: {\n handleIt() {\n assert.ok(false, 'application controller should not have received action!');\n }\n\n }\n }));\n this.add('controller:index', _controller.default.extend({\n actions: {\n handleIt() {\n assert.ok(true, 'controller received action properly');\n }\n\n }\n }));\n this.addTemplate('index', '');\n return this.visit('/').then(() => {\n (0, _internalTestHelpers.runTask)(() => this.$('#handle-it').click());\n });\n }\n\n });\n (0, _internalTestHelpers.moduleFor)('Rendering test: non-interactive actions', class extends _internalTestHelpers.RenderingTestCase {\n getBootOptions() {\n return {\n isInteractive: false\n };\n }\n\n [`@test doesn't attatch actions`](assert) {\n this.registerComponent('foo-bar', {\n ComponentClass: _helpers.Component.extend({\n actions: {\n fire() {\n assert.ok(false);\n }\n\n }\n }),\n template: ``\n });\n this.render('{{foo-bar tagName=\"\"}}');\n this.assertHTML('');\n this.$('button').click();\n }\n\n });\n});","define(\"@ember/-internals/glimmer/tests/integration/application/debug-render-tree-test\", [\"internal-test-helpers\", \"@ember/-internals/environment\", \"@ember/-internals/glimmer\", \"@ember/-internals/routing\", \"@ember/debug\", \"@ember/engine\", \"@glimmer/manager\", \"@glimmer/runtime\", \"@glimmer/util\", \"ember-template-compiler\", \"internal-test-helpers/lib/run\"], function (_internalTestHelpers, _environment, _glimmer, _routing, _debug, _engine, _manager, _runtime, _util, _emberTemplateCompiler, _run) {\n \"use strict\";\n\n function compileTemplate(templateSource, options) {\n return (0, _emberTemplateCompiler.compile)(templateSource, options);\n }\n\n function isExpectedFunc(expected) {\n return typeof expected === 'function';\n }\n\n if (_environment.ENV._DEBUG_RENDER_TREE) {\n (0, _internalTestHelpers.moduleFor)('Application test: debug render tree', class extends _internalTestHelpers.ApplicationTestCase {\n constructor() {\n super(...arguments);\n this._TEMPLATE_ONLY_GLIMMER_COMPONENTS = _environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS;\n _environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = true;\n }\n\n teardown() {\n super.teardown();\n _environment.ENV._TEMPLATE_ONLY_GLIMMER_COMPONENTS = this._TEMPLATE_ONLY_GLIMMER_COMPONENTS;\n }\n\n async '@test routes'() {\n this.addTemplate('index', 'Index');\n this.addTemplate('foo', 'Foo {{outlet}}');\n this.addTemplate('foo.index', 'index');\n this.addTemplate('foo.inner', '{{@model}}');\n this.addTemplate('bar', 'Bar {{outlet}}');\n this.addTemplate('bar.index', 'index');\n this.addTemplate('bar.inner', '{{@model}}');\n this.router.map(function () {\n this.route('foo', function () {\n this.route('inner', {\n path: '/:model'\n });\n });\n this.route('foo', function () {\n this.route('inner', {\n path: '/:model'\n });\n });\n });\n\n class PassThroughRoute extends _routing.Route {\n model({\n model\n }) {\n return model;\n }\n\n }\n\n this.add('route:foo.inner', PassThroughRoute);\n this.add('route:bar.inner', PassThroughRoute);\n await this.visit('/');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('index'),\n template: 'my-app/templates/index.hbs',\n bounds: this.elementBounds(this.element),\n children: []\n })]);\n await this.visit('/foo');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'foo',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('foo'),\n template: 'my-app/templates/foo.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'foo.index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('foo.index'),\n template: 'my-app/templates/foo/index.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n })]\n })]);\n await this.visit('/foo/wow');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'foo',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('foo'),\n template: 'my-app/templates/foo.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'foo.inner',\n args: {\n positional: [],\n named: {\n model: 'wow'\n }\n },\n instance: this.controllerFor('foo.inner'),\n template: 'my-app/templates/foo/inner.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n })]\n })]);\n await this.visit('/foo/zomg');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'foo',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('foo'),\n template: 'my-app/templates/foo.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'foo.inner',\n args: {\n positional: [],\n named: {\n model: 'zomg'\n }\n },\n instance: this.controllerFor('foo.inner'),\n template: 'my-app/templates/foo/inner.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n })]\n })]);\n }\n\n async '@test {{mount}}'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n
{{mount \"foo\"}}
\n
{{mount this.engineName}}
\n {{#if this.showMore}}\n
{{mount \"foo\" model=this.engineModel}}
\n
{{mount this.engineName model=this.engineModel}}
\n {{/if}}\n `);\n this.add('engine:foo', class extends _engine.default {\n constructor() {\n super(...arguments);\n this.isFooEngine = true;\n this.Resolver = _internalTestHelpers.ModuleBasedTestResolver;\n }\n\n init() {\n super.init(...arguments);\n this.register('template:application', compileTemplate((0, _internalTestHelpers.strip)`\n {{#if @model}}\n \n {{/if}}\n `, {\n moduleName: 'foo/templates/application.hbs'\n }));\n this.register('template:components/inspect-model', compileTemplate('{{@model}}', {\n moduleName: 'foo/components/inspect-model.hbs'\n }));\n }\n\n buildInstance(options) {\n var instance = super.buildInstance(options);\n instance['isFooEngineInstance'] = true;\n return instance;\n }\n\n });\n this.add('engine:bar', class extends _engine.default {\n constructor() {\n super(...arguments);\n this.Resolver = _internalTestHelpers.ModuleBasedTestResolver;\n }\n\n init() {\n super.init(...arguments);\n this.register('template:application', compileTemplate((0, _internalTestHelpers.strip)`\n {{#if @model}}\n \n {{/if}}\n `, {\n moduleName: 'bar/templates/application.hbs'\n }));\n this.register('template:components/inspect-model', compileTemplate('{{@model}}', {\n moduleName: 'bar/components/inspect-model.hbs'\n }));\n }\n\n buildInstance(options) {\n var instance = super.buildInstance(options);\n instance['isBarEngineInstance'] = true;\n return instance;\n }\n\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('engineName', 'bar');\n });\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }, {\n type: 'engine',\n name: 'bar',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isBarEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#dynamic')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'bar/templates/application.hbs',\n bounds: this.elementBounds(this.$('#dynamic')[0]),\n children: []\n }]\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('engineName', undefined);\n });\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }]);\n var model = {\n toString() {\n return 'some model';\n }\n\n };\n (0, _run.runTask)(() => {\n this.controllerFor('application').setProperties({\n showMore: true,\n engineModel: model\n });\n });\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }, {\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static-with-model')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static-with-model')[0]),\n children: [{\n type: 'component',\n name: 'inspect-model',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: null,\n template: 'foo/components/inspect-model.hbs',\n bounds: this.nodeBounds(this.$('#static-with-model')[0].lastChild),\n children: []\n }]\n }]\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('engineName', 'bar');\n });\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }, {\n type: 'engine',\n name: 'bar',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isBarEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#dynamic')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'bar/templates/application.hbs',\n bounds: this.elementBounds(this.$('#dynamic')[0]),\n children: []\n }]\n }, {\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static-with-model')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance.toString() === '(generated application controller)',\n bounds: this.elementBounds(this.$('#static-with-model')[0]),\n template: 'foo/templates/application.hbs',\n children: [{\n type: 'component',\n name: 'inspect-model',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: null,\n template: 'foo/components/inspect-model.hbs',\n bounds: this.nodeBounds(this.$('#static-with-model')[0].lastChild),\n children: []\n }]\n }]\n }, {\n type: 'engine',\n name: 'bar',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance['isBarEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#dynamic-with-model')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'bar/templates/application.hbs',\n bounds: this.elementBounds(this.$('#dynamic-with-model')[0]),\n children: [{\n type: 'component',\n name: 'inspect-model',\n args: {\n positional: [],\n named: {\n model\n }\n },\n instance: null,\n template: 'bar/components/inspect-model.hbs',\n bounds: this.nodeBounds(this.$('#dynamic-with-model')[0].lastChild),\n children: []\n }]\n }]\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').setProperties({\n showMore: false,\n engineName: undefined\n });\n });\n this.assertRenderTree([{\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance['isFooEngineInstance'] === true,\n template: null,\n bounds: this.elementBounds(this.$('#static')[0]),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {}\n },\n instance: instance => instance.toString() === '(generated application controller)',\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.$('#static')[0]),\n children: []\n }]\n }]);\n }\n\n async '@test routable engine'() {\n this.addTemplate('index', 'Index');\n var instance;\n this.add('engine:foo', class extends _engine.default {\n constructor() {\n super(...arguments);\n this.isFooEngine = true;\n this.Resolver = _internalTestHelpers.ModuleBasedTestResolver;\n }\n\n init() {\n super.init(...arguments);\n this.register('template:application', compileTemplate((0, _internalTestHelpers.strip)`\n {{outlet}}\n\n {{#if this.message}}\n \n {{/if}}\n `, {\n moduleName: 'foo/templates/application.hbs'\n }));\n this.register('template:index', compileTemplate('Foo', {\n moduleName: 'foo/templates/index.hbs'\n }));\n this.register('template:components/hello', compileTemplate('Hello {{@message}}', {\n moduleName: 'foo/components/hello.hbs'\n }));\n }\n\n buildInstance(options) {\n return instance = super.buildInstance(options);\n }\n\n });\n this.router.map(function () {\n this.mount('foo');\n });\n this.add('route-map:foo', function () {});\n await this.visit('/');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('index'),\n template: 'my-app/templates/index.hbs',\n bounds: this.elementBounds(this.element),\n children: []\n })]);\n await this.visit('/foo');\n this.assertRenderTree([this.outlet({\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance,\n template: null,\n bounds: this.elementBounds(this.element),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:application'),\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:index'),\n template: 'foo/templates/index.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n })]\n }]\n })]);\n (0, _run.runTask)(() => {\n var controller = instance.lookup('controller:application');\n controller.set('message', 'World');\n });\n this.assertRenderTree([this.outlet({\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance,\n template: null,\n bounds: this.elementBounds(this.element),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:application'),\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:index'),\n template: 'foo/templates/index.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }), {\n type: 'component',\n name: 'hello',\n args: {\n positional: [],\n named: {\n message: 'World'\n }\n },\n instance: null,\n template: 'foo/components/hello.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]\n }]\n })]);\n (0, _run.runTask)(() => {\n var controller = instance.lookup('controller:application');\n controller.set('message', undefined);\n });\n this.assertRenderTree([this.outlet({\n type: 'engine',\n name: 'foo',\n args: {\n positional: [],\n named: {}\n },\n instance: instance,\n template: null,\n bounds: this.elementBounds(this.element),\n children: [{\n type: 'route-template',\n name: 'application',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:application'),\n template: 'foo/templates/application.hbs',\n bounds: this.elementBounds(this.element),\n children: [this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: instance.lookup('controller:index'),\n template: 'foo/templates/index.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n })]\n }]\n })]);\n await this.visit('/');\n this.assertRenderTree([this.outlet({\n type: 'route-template',\n name: 'index',\n args: {\n positional: [],\n named: {\n model: undefined\n }\n },\n instance: this.controllerFor('index'),\n template: 'my-app/templates/index.hbs',\n bounds: this.elementBounds(this.element),\n children: []\n })]);\n }\n\n async '@test template-only components'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n this.addComponent('hello-world', {\n ComponentClass: null,\n template: '{{@name}}'\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', true);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'second'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', false);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@feature(EMBER_GLIMMER_SET_COMPONENT_TEMPLATE) templateOnlyComponent()'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n this.addComponent('hello-world', {\n ComponentClass: (0, _runtime.templateOnlyComponent)(),\n template: '{{@name}}'\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', true);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'second'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', false);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@feature(EMBER_GLIMMER_SET_COMPONENT_TEMPLATE) templateOnlyComponent() + setComponentTemplate()'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n this.addComponent('hello-world', {\n ComponentClass: (0, _manager.setComponentTemplate)(compileTemplate('{{@name}}', {\n moduleName: 'my-app/components/hello-world.hbs'\n }), (0, _runtime.templateOnlyComponent)())\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', true);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'second'\n }\n },\n instance: null,\n template: 'my-app/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', false);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: null,\n template: 'my-app/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@test classic components'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n this.addComponent('hello-world', {\n ComponentClass: _glimmer.Component.extend(),\n template: 'Hello World'\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', true);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'second'\n }\n },\n instance: instance => instance['name'] === 'second',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', false);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@test custom components'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n this.addComponent('hello-world', {\n ComponentClass: (0, _glimmer.setComponentManager)(_owner => {\n return {\n capabilities: (0, _manager.componentCapabilities)('3.13', {}),\n\n createComponent(_, {\n named: {\n name\n }\n }) {\n return {\n name\n };\n },\n\n getContext(instances) {\n return instances;\n }\n\n };\n }, {}),\n template: 'Hello World'\n });\n await this.visit('/');\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', true);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'second'\n }\n },\n instance: instance => instance['name'] === 'second',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => {\n this.controllerFor('application').set('showSecond', false);\n });\n this.assertRenderTree([{\n type: 'component',\n name: 'hello-world',\n args: {\n positional: [],\n named: {\n name: 'first'\n }\n },\n instance: instance => instance['name'] === 'first',\n template: 'my-app/templates/components/hello-world.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@test components'() {\n this.addTemplate('application', (0, _internalTestHelpers.strip)`\n \n\n {{#if this.showSecond}}\n \n {{/if}}\n `);\n await this.visit('/');\n var target = this.controllerFor('application');\n var inputToString = //;\n this.assertRenderTree([{\n type: 'component',\n name: 'input',\n args: {\n positional: [],\n named: {\n type: 'text',\n value: 'first'\n }\n },\n instance: instance => inputToString.test(instance.toString()),\n template: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n (0, _run.runTask)(() => target.set('showSecond', true));\n this.assertRenderTree([{\n type: 'component',\n name: 'input',\n args: {\n positional: [],\n named: {\n type: 'text',\n value: 'first'\n }\n },\n instance: instance => inputToString.test(instance.toString()),\n template: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }, {\n type: 'component',\n name: 'input',\n args: {\n positional: [],\n named: {\n type: 'checkbox',\n checked: false\n }\n },\n instance: instance => inputToString.test(instance.toString()),\n template: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs',\n bounds: this.nodeBounds(this.element.lastChild),\n children: []\n }]);\n (0, _run.runTask)(() => target.set('showSecond', false));\n this.assertRenderTree([{\n type: 'component',\n name: 'input',\n args: {\n positional: [],\n named: {\n type: 'text',\n value: 'first'\n }\n },\n instance: instance => inputToString.test(instance.toString()),\n template: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs',\n bounds: this.nodeBounds(this.element.firstChild),\n children: []\n }]);\n }\n\n async '@test + ``` + + The `@value` argument is two-way bound. If the user types text into the textarea, the `@value` + argument is updated. If the `@value` argument is updated, the text in the textarea is updated. + + In the following example, the `writtenWords` property on the component will be updated as the user + types 'Lots of text' into the text area of their browser's window. + + ```app/components/word-editor.js + import Component from '@glimmer/component'; + import { tracked } from '@glimmer/tracking'; + + export default class WordEditorComponent extends Component { + @tracked writtenWords = "Lots of text that IS bound"; + } + ``` + + ```handlebars + + ``` + + If you wanted a one way binding, you could use the `\n ```\n \n The `@value` argument is two-way bound. If the user types text into the textarea, the `@value`\n argument is updated. If the `@value` argument is updated, the text in the textarea is updated.\n \n In the following example, the `writtenWords` property on the component will be updated as the user\n types 'Lots of text' into the text area of their browser's window.\n \n ```app/components/word-editor.js\n import Component from '@glimmer/component';\n import { tracked } from '@glimmer/tracking';\n \n export default class WordEditorComponent extends Component {\n @tracked writtenWords = \"Lots of text that IS bound\";\n }\n ```\n \n ```handlebars\n \n ```\n \n If you wanted a one way binding, you could use the `