namespace.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. module.metadata = {
  6. "stability": "unstable"
  7. };
  8. const create = Object.create;
  9. const prototypeOf = Object.getPrototypeOf;
  10. /**
  11. * Returns a new namespace, function that may can be used to access an
  12. * namespaced object of the argument argument. Namespaced object are associated
  13. * with owner objects via weak references. Namespaced objects inherit from the
  14. * owners ancestor namespaced object. If owner's ancestor is `null` then
  15. * namespaced object inherits from given `prototype`. Namespaces can be used
  16. * to define internal APIs that can be shared via enclosing `namespace`
  17. * function.
  18. * @examples
  19. * const internals = ns();
  20. * internals(object).secret = secret;
  21. */
  22. function ns() {
  23. const map = new WeakMap();
  24. return function namespace(target) {
  25. if (!target) // If `target` is not an object return `target` itself.
  26. return target;
  27. // If target has no namespaced object yet, create one that inherits from
  28. // the target prototype's namespaced object.
  29. if (!map.has(target))
  30. map.set(target, create(namespace(prototypeOf(target) || null)));
  31. return map.get(target);
  32. };
  33. };
  34. // `Namespace` is a e4x function in the scope, so we export the function also as
  35. // `ns` as alias to avoid clashing.
  36. exports.ns = ns;
  37. exports.Namespace = ns;