text: /**
  * The state manager controls access to the state data. It monitors reads and writes, enforces accessibility and mutability rules, and executes change handlers for any listeners.
  * The object returned by the worker function is the root state proxy. The proxy is created using the initial state, if provided, and is configured using any instruction properties on the initial state object.
  * The state manager worker can be executed 1..n times to create 1..n independent state proxies. This provides the ability to use several independent state controls in a single application.
  * Properties on the root state that are objects will be treated as branches of the root state, inheriting instructions, as well as having the option to define their own instructions.
  * @factory
  * @feature state_instructions
  *   @description The state accepts several instuctions which modify how the state objects operate. Instructions are added as properties to the target object, consumed and removed from the target object's properties. Each branch in the state tree can have it's own set of instructions, any instructions not provided are inherited from the branches parent.
  *   @instruction __nolisten
  *   @instruction __mutibility
  *   @instruction __shared
  *   @instruction __access
  *   @instruction __async
  *   @instruction __concurrent
  *   @instruction __noref
  *   @instruction __descriptors
  * @feature state_links
  *   @description There are 3 types of state links; sym, soft and hard. The links create bridges between 2 different namespaces; Namespace A and Namespace Z.
  *   @type `sym` A symbolic link creates a link between namespace Z and namespace A. Each namespace represents the same target object. Updates to the target object's properties, from either end, will result in the listeners being fired for each namespace. Namespace Z is dependent on Namespace A, but not the other way around. If the target object for namespace A is changed, namespace Z will represent the new reference. If the target object for namespace Z is changed, say to namespace T, the link will be broken with namespace A and a new link will be made with namespace T. A symbolic link is created using either symbolic link notation or making a literal symbolic link by assigning the target object of namespace A to namespace Z.
  *   @type `soft` A soft link is similar to a symbolic link except that if the target object for either namespace is changed, the link is broken; neither namespace is depenent on the other. A soft link can only be created using soft link notation.
  *   @type `hard` A hard link is similar to a symbolic link except that if the target object for either namespace is changed, both namespaces reference the new target object; each namespace is dependent on the other. A hard link can only be created using hard link notation
  *   @feature symbolic_link_notation
  *       @description To create a symbolic link using a property prefix the property name with `<-` and make the property value the fq namespace of link target.
  *   @feature soft_link_notation
  *       @description To create a soft link prefix the property name name with `<~` and make the property value the fq namespace of link target.
  *   @feature hard_link_notation
  *       @description To create a hard link prefix the property name name with `<=` and make the property value the fq namespace of link target.
  * @interface iStateMeta
  *   @property {boolean} [__nolisten] When set to true, change listeners will not be fired for any property on this object or it's descendants (superseded only by state instuctions on the descendant).
  *   @property {boolean} [__mutibility] Sets the object's mutibility, freeze, seal, noextend and open; default is freeze.
  *   @property {boolean|object} [__shared] If set to true, or an object, the proxy object's properties are shared with its ... ???. If the `__shared` value is an object, that object will be used to further define how the properties are shared.
  *   @property {string} [__access] Sets access permissions
  *   @property {boolean} [__async] If true, the change listeners will be fired asyncronously.
  *   @property {boolean} [__concurrent] If true, the change listeners will be ran concurrently (__async is forced to true)
  *   @property {boolean} [__noref] If true, the external reference to the object value will be removed using a deep copy; will not work with circular referenced object or functions.
  *   @property {object} [__descriptors] An object with 1..n property descriptors which will be applied to the object's properties.
  *   @property {string} [__name] The property name
  *   @property {string} [__namespace] The fully qualified namespace of the property
  *   @property {string} [__last] The last time the object was accessed
  *   @property {string} [__uuid] The existing uuid of the object, if omitted one is generated.
  */
  function _StateManager(
      promise
      , performance
      , statenet_common_listenerManager
      , statenet_common_listener
      , utils_uuid
      , utils_copy
      , utils_update
      , utils_applyIf
      , utils_apply
      , utils_getType
      , utils_lookup
      , utils_reference
      , weakMap
      , is_object
      , is_objectValue
      , is_func
      , is_array
      , is_numeric
      , is_bool
      , is_promise
      , reporter
      , defaults
      , constants
      , infos
      , errors
  ) {
      /**
      * @constants
      */
      const cnsts = {
          "stateLinkTypes": {
              "<-": "sym"
              , "<=": "hard"
              , "<~": "soft"
          }
          , "stateLinkPrefixes": [
              "<-"
              , "<="
              , "<~"
          ]
          , "stateLinkNames": [
              "sym"
              , "hard"
              , "soft"
          ]
          , "asyncFunctionNames": [
              "get$"
              , "set$"
              , "delete$"
              , "apply$"
          ]
          , "asyncFunctions": {
              "get$": asyncGetHandler
              , "set$": asyncSetHandler
              , "delete$": asyncDeleteHandler
              , "apply$": asyncApplyHandler
          }
      }
      /**
      * Allows access to the target object's namespace
      * @symbol
      */
      , NamespaceSymbol = Symbol("namespace")
      /**
      * @alias
      */
      , listenerManager = statenet_common_listenerManager
      /**
      * @alias
      */
      , listener = statenet_common_listener
      /**
      * A regular expression pattern for replacing dots with escaped dots
      * @property
      */
      , DOT_PATT = /(?:(?<![\\])|(?<=[\\]{2}))[.]/g
      ;
  
      //add a static lookup for stateful checking
      StateManager.isStateful = isStateful;
  
      StateManager.findStateful = findStateful;
  
      return StateManager;
  
      /**
      * @worker
      *   @async
      *   @property {object} config An object with the state manager configuration
      *   @property {object} [rootState] An optional object used to initialize the state manager.
      */
      function StateManager(
          config
          , rootTarget
      ) {
          //initialize the state manager
          var meta = initialize(
              config
              , rootTarget
          );
          //create the root state proxy
          return createProxy(
              meta.rootNamespace
              , rootTarget
              , meta
          );
      }
  
      /**
      * sets up the external storage and intakes the initial state if provided
      * @function
      */
      function initialize(config, target) {
          //if the configuration has been setup then skip this
          if (is_object(configuration)) {
              return;
          }
          //see if we are removing the reference from the external target
          if (!!target && target.__noref === true) {
              target = removeReference(
                  target
              );
          }
          //ensure we have a target
          if (!target) {
              target = {};
          }
          //ensure we have a configuration, removing external references
          var configuration = is_object(config)
              ? utils_copy(
                  config
              )
              : {}
          ;
          //add the defaults for any missing configuration
          configuration = utils_update(
              configuration
              , utils_copy(
                  defaults.statenet.stateManager.config
              )
          );
  
          var meta = {
              "rootNamespace": configuration.namespace || "$"
              , "rootTarget": target
              , "arrayChangeMap": new weakMap()
              , "proxyMap": new weakMap()
              , "arrayOpMap": new weakMap()
              , "metaMap": new weakMap()
              , "stateLinks": {
                  "sym": {
                      "links": {}
                      , "sideA": []
                      , "sideZ": []
                  }
                  , "hard": {
                      "links": {}
                      , "sideA": []
                      , "sideZ": []
                  }
                  , "soft": {
                      "links": {}
                      , "sideA": []
                      , "sideZ": []
                  }
              }
          };
          //apply the default instructions to the meta
          utils_applyIf(
              utils_copy(
                  defaults.statenet.stateManager.instructions
              )
              , meta
          );
  
          //if we're using paging then setup the external storage
          if (configuration.paging === true) {
              setupExternalStorage(
  
              );
          }
  
          return meta;
      }
      /**
      * Initializes the offline storage that will be used to page state branches
      * @function
      */
      function setupExternalStorage() {
          //TODO: setup offline storage
          throw new Error(
              `${errors.statenet.statenet.not_implemented} (_StateManager.StateManager.setupExternalStorage)`
          );
      }
  
      /**
      * @function
      */
      function createProxy(name, target, parentMeta) {
          var meta = parentMeta.metaMap.get(target)
          , proxy
          ;
          //if there is no meta data then this must be our first encounter
          if (!meta) {
              //intake the target and create a new meta object
              meta = intakeTarget(
                  name
                  , target
                  , parentMeta
              );
          }
          //create a proxy if there isn't one yet
          if (!meta.hasOwnProperty('proxy')) {
              //see if we are going to watch
              if (meta.__nowatch === true) {
                  meta.proxy = target;
              }
              //create a revokable proxy if marked
              if (meta.__revokable === true) {
                  meta.proxy = Proxy.revocable(
                      target
                      , createTrapHandlers(
                          meta
                      )
                  );
              }
              //otherwise create a normal proxy
              else {
                  meta.proxy = new Proxy(
                      target
                      , createTrapHandlers(
                          meta
                      )
                  );
              }
          }
  
          return meta.proxy;
      }
      /**
      * @function
      */
      function intakeTarget(name, target, parentMeta) {
          //get the meta data
          var meta = extractMeta(
              name
              , target
              , parentMeta
          );
          parentMeta.metaMap.set(target, meta);
          //if the target is a function then skip the rest
          if (is_func(target)) {
              return meta;
          }
          //add any descriptors from the meta
          if (is_object(meta.__descriptors)) {
              addDescriptors(
                  target
                  , meta.__descriptors
              );
          }
          //process the target propertes
          processTargetProperties(
              target
              , meta
          );
          //return the meta object and the target in case we de referenced it
          return meta;
      }
  
      /**
      * @function
      */
      function extractMeta(name, target, parentMeta) {
          //create a new meta object with the parentMeta as the prototype
          //  each target object should chain it's parent object's meta
          //  so it inherit's the parent's instructions
          var meta = Object.create(
              parentMeta
          );
          //if the target is an array, and the first member is an object, with instruction properties, then that is the meta
          if (is_array(target) && is_object(target[0])) {
              extractArrayMeta(
                  name
                  , target
                  , meta
              );
          }
          //if the target is an object then find any properties that map to instructions
          else {
              extractObjectMeta(
                  name
                  , target
                  , meta
              );
          }
          //set the naming
          meta.__name = name;
          meta.__namespace = !!parentMeta && !!parentMeta.__namespace
              ? `${parentMeta.__namespace}.${name}`
              : name
          ;
          //set the initial timestamp
          meta.__last = performance.now();
  
          return meta;
      }
      /**
      * @function
      */
      function extractObjectMeta(name, target, meta) {
          Object.keys(target)
          .forEach(
              function checkEachKey(key) {
                  if (isInstruction(key)) {
                      meta[key] = utils_copy(target[key]);
                      delete target[key];
                  }
              }
          );
  
          return meta;
      }
      /**
      * @function
      */
      function extractArrayMeta(name, target, meta) {
          var isMeta =
              Object.keys(target[0])
              .every(
                  function everyPropIsInstruction(key) {
                      return isInstruction(key);
                  }
              )
          , instructions
          ;
          if (isMeta) {
              //remove the instruction object from the array
              instructions = target.shift();
              //add the instructions to the meta data
              utils_apply(
                  utils_copy(
                      instructions
                  )
                  , meta
              );
          }
  
          return meta;
      }
  
      /**
      * @function
      */
      function removeReference(target) {
          //let's not copy functions
          if (is_func(target)) {
              return target;
          }
          //create a deep copy of the target
          var targetCopy = utils_copy(
              target
          )
          , proto
          , newTarget
          ;
          //if the target is an object, we should set the prototype
          if (is_object(target)) {
              proto = Object.getPrototypeOf(target);
              if (proto !== Object) {
                  //create the internal object, preserving the prototype
                  newTarget = Object.create(
                      Object.getPrototypeOf(target)
                  );
                  //apply the copy of the object value's properties.
                  targetCopy = utils_apply(
                      targetCopy
                      , newTarget
                  );
              }
          }
  
          return targetCopy;
      }
  
      /**
      * @function
      */
      function addDescriptors(target, descriptors) {
          ///INPUT VALIDATION
          ///TODO: check to see if the descriptors are properly formatted
          ///END INPUT VALIDATION
          Object.defineProperties(
              target
              , descriptors
          );
      }
  
      /**
      * @function
      */
      function processTargetProperties(target, meta) {
          Object.keys(target)
          .forEach(
              processTargetProperty.bind(
                  null
                  , target
                  , meta
              )
          );
      }
      /**
      * @function
      */
      function processTargetProperty(target, meta, key) {
          var value = target[key]
          , name
          ;
          //prototype properties should not be trapped
          if (!target.hasOwnProperty(key)) {
              return;
          }
          //see if the name has state link notation
          if (cnsts.stateLinkPrefixes.indexOf(key.substring(0, 2)) != -1) {
              processStateLinkNotation(
                  target
                  , meta
                  , key
              );
          }
          //if the value is an object, process that
          if (is_objectValue(value) || is_func(value)) {
              intakeTarget(
                  key
                  , value
                  , meta
              );
          }
      }
      /**
      * @function
      */
      function processStateLinkNotation(target, meta, key) {
          var linkType = cnsts.stateLinkTypes[
              key.substring(0, 2)
          ]
          , propName = key.substring(2)
          , linkZNamespace = getNamespace(
              meta
              , propName
          )
          , linkANamespace = target[key]
          , linkTarget = utils_lookup(
              linkANamespace.indexOf("$.") === 0
                  ? linkANamespace.substring(2)
                  : linkANamespace
              , target
          )
          ;
          //remove the target property with the link notation
          delete target[key];
          //add the property to the target with the link target's value
          target[propName] = linkTarget;
          //add the link to the collection
          createStateLink(
              meta
              , linkType
              , linkANamespace
              , linkZNamespace
          );
      }
  
      /**
      * @function
      */
      function createTrapHandlers(meta) {
          return {
              "get": getHandler.bind(null, meta)
              , "set": setHandler.bind(null, meta)
              , "deleteProperty": deleteHandler.bind(null, meta)
              , "apply": applyHandler.bind(null, meta)
          };
      }
  
  
      /**
      * @function
      */
      function getHandler(meta, target, propName, receiver) {
          var returnValue = doGet(
              meta
              , target
              , propName
              , receiver
          );
  
          return returnValue;
      }
      /**
      * @function
      */
      function setHandler(meta, target, propName, value, receiver) {
          //perform the set operation
          var setOperation = doSet(
              meta
              , target
              , propName
              , value
              , receiver
          );
          if (is_bool(setOperation)) {
              return setOperation;
          }
  
          if (!is_array(setOperation)) {
              setOperation = [setOperation];
          }
          //fire the listeners
          for(let index in setOperation) {
              fireListener(
                  meta
                  , "set"
                  , setOperation[index]
              );
          }
          return true;
      }
      /**
      * @function
      */
      function deleteHandler(meta, target, propName) {
          //perform the delete operation
          var deleteOperation = doDelete(
              meta
              , target
              , propName
          );
          //fire the listeners
          if (!!deleteOperation) {
              fireListener(
                  meta
                  , "delete"
                  , deleteOperation
              );
  
              return deleteOperation.success;
          }
          else {
              return false;
          }
      }
      /**
      * @function
      */
      function applyHandler(meta, target, thisArg, argList) {
          //perform the apply operation
          var applyOperation = doApply(
              meta
              , target
              , thisArg
              , argList
          );
          //fire the listeners
          fireListener(
              meta
              , "apply"
              , applyOperation
          );
  
          return applyOperation.result;
      }
      /**
      * @function
      */
      async function asyncGetHandler(meta, target, propName) {
          var itemRef = utils_reference(
              propName
              , target
          );
          //if the item wasn't found return
          if (!itemRef.found) {
              return;
          }
          //
          return doGet(
              meta.metaMap.get(itemRef.parent)
              , itemRef.parent
              , itemRef.index
          );
      }
      /**
      * @function
      */
      async function asyncSetHandler(meta, target, propName, value) {
          var itemRef = utils_reference(
              propName
              , target
          )
          , setOperation
          , proc = promise.resolve()
          ;
          if (!itemRef.found) {
              return;
          }
          //run the do set operation
          setOperation = doSet(
              meta.metaMap.get(itemRef.parent)
              , itemRef.parent
              , itemRef.index
              , value
          );
          //if the operation returned a boolean then we aren't fireing any
          //  listeners
          if (is_bool(setOperation)) {
              return setOperation;
          }
          if (!is_array(setOperation)) {
              setOperation = [setOperation];
          }
          //fire the listeners asyncronously
          for(let index in setOperation) {
              proc = proc.then(
                  function thenFireNextEvent() {
                      return fireListenerAsync(
                          meta
                          , "set"
                          , setOperation[index]
                      );
                  }
              );
          }
          return proc;
      }
      /**
      * @function
      */
      async function asyncDeleteHandler(meta, target, propName) {
          var itemRef = utils_reference(
              propName
              , target
          )
          , deleteOperation
          , proc = promise.resolve()
          ;
          if (!itemRef.found) {
              return;
          }
          //run the do set operation
          deleteOperation = doDelete(
              meta.metaMap.get(itemRef.parent)
              , itemRef.parent
              , itemRef.index
          );
          //if the operation returned a boolean then we aren't fireing any
          //  listeners
          if (is_bool(deleteOperation)) {
              return deleteOperation;
          }
          //fire the listener asyncronously
          return fireListenerAsync(
              meta
              , "delete"
              , deleteOperation
          );
      }
      /**
      * @function
      */
      async function asyncApplyHandler(meta, target, propName, thisArg, argList) {
          var itemRef = utils_reference(
              propName
              , target
          )
          , applyOperation
          , proc = promise.resolve()
          ;
          if (!itemRef.found) {
              return;
          }
          //run the do set operation
          applyOperation = doApply(
              meta.metaMap.get(itemRef.value)
              , itemRef.value
              , thisArg
              , argList
          );
          //if the operation returned a boolean then we aren't fireing any
          //  listeners
          if (is_bool(applyOperation)) {
              return applyOperation;
          }
          //fire the listener asyncronously
          await fireListenerAsync(
              meta
              , "apply"
              , applyOperation
          );
  
          return applyOperation.result;
      }
  
      /**
      * @function
      */
      function doGet(meta, target, propName, receiver) {
          //verify access
          hasAccess(
              meta
              , "get"
              , propName
          );
          //the state manager doesn't trap symbols, passthrough
          ///NOTE: This handles return of the namespace symbol explicitly
          if (typeof propName === "symbol") {
              //NamespaceSymbol returns the target's fq namespace
              if (propName === NamespaceSymbol) {
                  //if the receiver exists, but isn't the target's proxy
                  //  return undefined
                  if (!!receiver && receiver !== meta.proxy) {
                      return;
                  }
                  return meta.__namespace;
              }
              return target[propName];
          }
          //if this is an instruction property then process it
          if (isInstruction(propName)) {
              return instructionHandler(
                  meta
                  , "get"
                  , propName
              );
          }
          //if this is a listener then process it
          if (listenerManager.hasOwnProperty(propName)) {
              return listenerMethodHandler(
                  meta
                  , "get"
                  , propName
              );
          }
          //handle async function names
          if (isAsyncFunction(propName)) {
              return cnsts.asyncFunctions[propName].bind(
                  null
                  , meta
                  , target
              );
          }
          //prototype properties should not be trapped
          if (!target.hasOwnProperty(propName)) {
              return target[propName];
          }
          //get the return value
          var returnValue = target[propName];
          //intake and create a proxy for new objects
          if (is_objectValue(returnValue) || is_func(returnValue)) {
              returnValue = createProxy(
                  propName
                  , returnValue
                  , meta
              );
          }
  
          return returnValue;
      }
      /**
      * @function
      */
      function doSet(meta, target, propName, value, receiver) {
          //if there is a receiver, but it isn't a this target's proxy, that means
          //  this is the receiver's stateful prototype. Don't write the property
          //  to the prototype, define it on the receiver
          if (!!receiver && meta.proxy !== receiver) {
              Object.defineProperty(
                  receiver
                  , propName
                  , {
                      "enumerable": true
                      , "writable": true
                      , "value": value
                  }
              );
              return true;
          }
          //verify access
          hasAccess(
              meta
              , "apply"
              , propName
          );
          //the state doesn't trap symbols, passthrough
          if (typeof propName === "symbol") {
              //if the NamespaceSymbols is written to, ignore and fail quietly
              if (propName === NamespaceSymbol) {
                  return false;
              }
              target[propName] = value;
              return true;
          }
          ///LOGGING
          reporter.state(
              `${infos.statenet.set_trap_called} ${propName}`
          );
          ///END LOGGING
          //if this is an instruction then process it
          if (isInstruction(propName)) {
              return instructionHandler(
                  meta
                  , "set"
                  , propName
                  , value
              );
          }
          //if this is a listener then process it
          if (listenerManager.hasOwnProperty(propName)) {
              return listenerMethodHandler(
                  meta
                  , "set"
                  , propName
              );
          }
          //if the property was not found on the target it will fall to the
          //  prototype. Check to see if the receiver's proto is stateful
          //  if so then define the property on the receiver
          if (
              !target.hasOwnProperty(propName)
              && isStateful(Object.getPrototypeOf(receiver))
          ) {
              //use define property otherwise setting the property directly
              //   will cause this trap to be called recursively
              Object.defineProperty(
                  receiver
                  , propName
                  , {
                      "enumerable": true
                      , "writable": true
                      , "value": value
                  }
              );
              //
              return true;
          }
          //see if the target has this property
          var hasProp = target.hasOwnProperty(propName)
          , namespace = getNamespace(
              meta
              , propName
          )
          , oldValue = target[propName]
          , newValue
          , typeChange = false
          ;
          //see if we changed the type
          if (!!hasProp && utils_getType(oldValue) !== utils_getType(value)) {
              typeChange = true;
          }
          //if this is an array handle those seperately
          if (is_array(target)) {
              return handleSetArray(
                  meta
                  , target
                  , propName
                  , value
                  , oldValue
                  , hasProp
                  , typeChange
              );
          }
          //process any state link updates
          newValue = processStateLinks(
              meta
              , namespace
              , value
              , oldValue
          );
          //update the value
          target[propName] = newValue;
  
          //create the meta data about the set operation
          return {
              "namespace": namespace
              , "name": propName
              , "parentNamespace": meta.__namespace
              , "action": "set"
              , "miss": !hasProp
              , "typeChange": typeChange
              , "value": doGet(
                  meta
                  , target
                  , propName
                  , receiver
              )
              , "oldValue": oldValue
          };
      }
      /**
      * @function
      */
      function handleSetArray(
          meta
          , target
          , propName
          , value
          , oldValue
          , hasProp
          , typeChange
      ) {
          //get the change list for the target array
          var changeList = meta.arrayChangeMap.get(
              target
          )
          //get the operatation set for the target array
          , op = meta.arrayOpMap.get(
              target
          )
          , result = false
          ;
          //if this is not a length change then it is part of a change cycle
          if (propName !== 'length') {
              //set the value
              target[propName] = value;
              //if there isn't a change list, this is the start of a cycle
              if (!changeList) {
                  meta.arrayChangeMap.set(
                      target
                      , (changeList = [])
                  );
              }
              //add a change record to the list
              changeList.push(
                  {
                      "action": "set"
                      , "propName": propName
                      , "miss": !hasProp
                      , "typeChange": typeChange
                      , "value": value
                      , "oldValue": oldValue
                  }
              );
              //if there isn't an operation then process the update immediately
              if (!op) {
                  meta.arrayChangeMap.delete(
                      target
                  );
                  //this results in a single event detail
                  result = processArrayChangeCycle(
                      meta
                      , target
                      , changeList
                  );
              }
          }
          //if there isn't a change list then this is just an array length update
          else if (!changeList) {
              //this results in an array of event detail
              result = handleArrayLengthChange(
                  meta
                  , target
                  , propName
                  , value
                  , oldValue
              );
              //set the value
              target[propName] = value;
          }
          //otherwise this is the end of a change cycle
          else {
              //remove the array change map for this target
              meta.arrayChangeMap.delete(
                  target
              );
              meta.arrayOpMap.delete(
                  target
              );
              //this results in a single event detail
              result = processArrayChangeCycle(
                  meta
                  , target
                  , changeList
              );
              //set the value
              target[propName] = value;
          }
  
          return result;
      }
      /**
      * @function
      */
      function handleArrayLengthChange(
          meta
          , target
          , propName
          , newLength
          , oldLength
      ) {
          var namespace
          , eventDetails = []
          ;
          //if this is reducing, fire delete events
          if (oldLength > newLength) {
              while(oldLength > newLength) {
                  oldLength--;
                  namespace =  getNamespace(
                      meta
                      , propName
                  );
                  //fire a listener for each delete
                  eventDetails.push(
                      {
                          "namespace": namespace
                          , "name": propName
                          , "parentNamespace": meta.__namespace
                          , "action": "delete"
                          , "arrayAction": "delete"
                          , "miss": !!target[propName]
                          , "success": true
                      }
                  );
              }
  
              return eventDetails;
          }
  
          return true;
      }
      /**
      * @function
      */
      function doDelete(meta, target, propName) {
          //the state doesn't use symbols, passthrough
          if (typeof propName === "symbol") {
              return delete target[propName];
          }
          ///LOGGING
          reporter.state(
              `${infos.statenet.delete_trap_called} ${propName}`
          );
          ///END LOGGING
          //verify access
          hasAccess(
              meta
              , "apply"
              , propName
          );
          //if this is an instruction then process it
          if (isInstruction(propName)) {
              return instructionHandler(
                  meta
                  , "delete"
                  , propName
                  , value
              );
          }
          //if this is a listener then process it
          if (listenerManager.hasOwnProperty(propName)) {
              return listenerMethodHandler(
                  meta
                  , "delete"
                  , propName
              );
          }
          //if the target is an array then take a different path
          if (is_array(target)) {
              return handleDeleteArray(
                  meta
                  , target
                  , propName
              );
          }
          //see if the target has this property
          var hasProp = target.hasOwnProperty(propName)
          , namespace = getNamespace(
              meta
              , propName
          )
          , value = target[propName]
          , result
          ;
          //remove any state links if the value is an object
          deleteStateLinks(
              meta
              , namespace
          );
  
          //attempt to delete the value
          result = delete target[propName];
  
          return {
              "namespace": namespace
              , "name": propName
              , "parentNamespace": meta.__namespace
              , "action": "delete"
              , "miss": !hasProp
              , "success": result
          };
      }
      /**
      * @function
      */
      function handleDeleteArray(meta, target, propName) {
          //get the change list for the target
          var changeList = meta.arrayChangeMap.get(
              target
          )
          , oldValue
          , success
          ;
          //if there isn't a change list then this is a straight delete of the property
          if (!changeList) {
              oldValue = target[propName];
              success = delete target[propName];
              return processArrayChangeCycle(
                  meta
                  , target
                  , [
                      {
                          "action": "delete"
                          , "propName": propName
                          , "oldValue": oldValue
                          , "value": null
                          , "miss": false
                          , "success": success
                      }
                  ]
              );
          }
          else {
              oldValue = target[propName];
              success = delete target[propName];
              //add a change record to the list and wait for length change
              changeList.push(
                  {
                      "action": "delete"
                      , "propName": propName
                      , "oldValue": oldValue
                      , "miss": false
                      , "success": success
                  }
              );
          }
  
          return;
      }
      /**
      * @function
      */
      function doApply(meta, target, thisArg, argList) {
          ///LOGGING
          reporter.state(
              `${infos.statenet.apply_trap_called} ${meta.__namespace}`
          );
          ///END LOGGING
          //verify access
          hasAccess(
              meta
              , "apply"
          );
          //run the function and store the result
          var result = target
              .apply(
                  thisArg
                  , argList
              )
          , [parentNamespace, propName] = parseNamespace(
              meta.__namespace
          );
  
          return {
              "namespace": meta.__namespace
              , "name": propName
              , "parentNamespace": parentNamespace
              , "action": "apply"
              , "scope": thisArg
              , "arguments": argList
              , "result": result
          };
      }
      /**
      * @function
      */
      function processArrayChangeCycle(meta, target, changeList) {
          var firstEntry = changeList[0]
          , lastEntry = changeList[changeList.length - 1]
          , secondLastEntry = changeList[changeList.length - 2]
          , oldValue, value
          , action, arrayAction
          , miss, typeChange, success
          , propName, eventDetail, namespace
          ;
  
          //if the last member is a delete, then this is a delete operation
          if (lastEntry.action === "delete") {
              //the first change has the deleted value and key
              propName = firstEntry.propName;
              oldValue = firstEntry.oldValue;
              typeChange = false;
              action = arrayAction = "delete";
              success = firstEntry.success;
              miss = false;
          }
          //if there is only one entry then this is an append or replace
          else if (changeList.length === 1) {
              propName = firstEntry.propName;
              value = firstEntry.value;
              typeChange = firstEntry.typeChange;
              action = "set";
              if (firstEntry.miss) {
                  arrayAction = "append";
                  miss = true;
              }
              else {
                  arrayAction = "replace";
                  miss = false;
                  oldValue = firstEntry.oldValue;
              }
          }
          //otherwise this is an insert operation
          else {
              //the final change should be the insert
              propName = lastEntry.propName;
              value = lastEntry.value;
              oldValue = secondLastEntry.value;
              typeChange = secondLastEntry.typeChange;
              action = "set";
              arrayAction = "insert";
              miss = false;
          }
  
          //create the namespace
          namespace =  getNamespace(
              meta
              , propName
          );
  
          eventDetail = {
              "namespace": namespace
              , "name": propName
              , "parentNamespace": meta.__namespace
              , "action": action
              , "arrayAction": arrayAction
              , "miss": miss
          };
  
          if (action === "delete") {
              eventDetail.success = success;
              deleteStateLinks(
                  meta
                  , namespace
              );
          }
          else {
              eventDetail.typeChange = typeChange;
              eventDetail.value = doGet(
                  meta
                  , target
                  , propName
              );
              eventDetail.oldValue = oldValue;
              processStateLinks(
                  meta
                  , namespace
                  , value
                  , oldValue
              );
          }
  
          return eventDetail;
      }
  
  
  
      /**
      * @function
      */
      function processStateLinks(meta, namespace, value, oldValue) {
          var links = meta.stateLinks
          , linkPath
          , linkRef
          , newValue = value
          , linkANamespace
          , linkMeta
          , linkIndexes
          ;
          //if the new value is stateful then get the namespace and target object
          if (isStateful(value)) {
              //get the namespace of the stateful value
              linkANamespace = value[NamespaceSymbol];
              //lookup the target object using the namespace
              newValue = utils_lookup(
                  linkANamespace.substring(2) //strip off leading `$.`
                  , meta.rootTarget
              );
          }
          //symbolic link A side
          if ((linkIndexes = getLinkIndexes(links.sym.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //update the Z side with the new target value
                  linkPath = links.sym.sideZ[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  if ((linkMeta = meta.metaMap.get(oldValue))) {
                      meta.metaMap.delete(oldValue);
                      delete linkMeta.proxy;
                      meta.metaMap.set(newValue, linkMeta);
                  }
                  linkRef.parent[linkRef.index] = newValue;
              }
          }
          //symbolic link Z side
          if ((linkIndexes = getLinkIndexes(links.sym.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //break the link with the A namespace
                  links.sym.sideA.splice(linkIndex, 1);
                  links.sym.sideZ.splice(linkIndex, 1);
              }
          }
          //hard link A side
          if ((linkIndexes = getLinkIndexes(links.hard.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //update the Z side with the new target value
                  linkPath = links.hard.sideZ[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  if ((linkMeta = meta.metaMap.get(oldValue))) {
                      meta.metaMap.delete(oldValue);
                      delete linkMeta.proxy;
                      meta.metaMap.set(newValue, linkMeta);
                  }
                  linkRef.parent[linkRef.index] = newValue;
              }
          }
          //hard link Z side
          if ((linkIndexes = getLinkIndexes(links.hard.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //update the A side with the new target value
                  linkPath = links.hard.sideA[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  if ((linkMeta = meta.metaMap.get(oldValue))) {
                      meta.metaMap.delete(oldValue);
                      delete linkMeta.proxy;
                      meta.metaMap.set(newValue, linkMeta);
                  }
                  linkRef.parent[linkRef.index] = newValue;
              }
          }
          //soft link A side
          if ((linkIndexes = getLinkIndexes(links.soft.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //break the link with the Z side
                  links.soft.sideA.splice(linkIndex, 1);
                  links.soft.sideZ.splice(linkIndex, 1);
              }
          }
          //soft link Z side
          if ((linkIndexes = getLinkIndexes(links.soft.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //break the link with the Z side
                  links.soft.sideA.splice(linkIndex, 1);
                  links.soft.sideZ.splice(linkIndex, 1);
              }
          }
          //if the new value is stateful then this is a new symbolic link
          if (!!linkANamespace) {
              //this is a literal sym link
              createStateLink(
                  meta
                  , "sym"
                  , linkANamespace
                  , namespace
              );
          }
  
          return newValue;
      }
      /**
      * @function
      */
      function createStateLink(meta, linkType, linkANamespace, linkZNamespace) {
          meta.stateLinks[linkType].sideA.push(
              linkANamespace
          );
          meta.stateLinks[linkType].sideZ.push(
              linkZNamespace
          );
      }
      /**
      * @function
      */
      function deleteStateLinks(meta, namespace) {
          var links = meta.stateLinks
          , linkPath
          , linkRef
          ;
          //symbolic link A side
          if ((linkIndexes = getLinkIndexes(links.sym.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //delete the value on the Z side
                  linkPath = links.sym.sideZ[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  delete linkRef[linkRef.index];
                  //remove the link
                  links.sym.sideA.splice(linkIndex, 1);
                  links.sym.sideZ.splice(linkIndex, 1);
              }
          }
          //symbolic link Z side
          if ((linkIndexes = getLinkIndexes(links.sym.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //remove the link
                  links.sym.sideA.splice(linkIndex, 1);
                  links.sym.sideZ.splice(linkIndex, 1);
              }
          }
          //hard link A side
          if ((linkIndexes = getLinkIndexes(links.hard.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //delete the value on the Z side
                  linkPath = links.hard.sideZ[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  delete linkRef[linkRef.index];
              }
          }
          //hard link Z side
          if ((linkIndexes = getLinkIndexes(links.hard.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //delete the value on the A side
                  linkPath = links.hard.sideA[linkIndex];
                  linkRef = utils_reference(
                      cleanNamespace(linkPath)
                      , meta.rootTarget
                  );
                  delete linkRef[linkRef.index];
              }
          }
          //soft link A side
          if ((linkIndexes = getLinkIndexes(links.soft.sideA, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //remove the link
                  links.soft.sideA.splice(linkIndex, 1);
                  links.soft.sideZ.splice(linkIndex, 1);
              }
          }
          //soft link Z side
          if ((linkIndexes = getLinkIndexes(links.soft.sideZ, namespace))) {
              for(let linkIndex in linkIndexes) {
                  //remove the link
                  links.soft.sideA.splice(linkIndex, 1);
                  links.soft.sideZ.splice(linkIndex, 1);
              }
          }
      }
      /**
      * @function
      */
      function getLinkIndexes(linkSide, namespace) {
          var links = []
          , index = -1
          ;
  
          while((index = linkSide.indexOf(namespace, index + 1)) !== -1) {
              links.push(
                  index
              );
          }
  
          if (links.length === 0) {
              return;
          }
  
          return links;
      }
  
  
      /**
      * Checks to see if the caller has permissions to access this property
      * @function
      */
      function hasAccess(meta, trapName, propName) {
          var hasAccess = true;
          ///TODO: add permissions code
          if(!hasAccess) {
              throw new Error(
                  `${errors.statenet.unauthorized_access} (${action} ${propName})`
              );
          }
      }
      /**
      * @function
      */
      function instructionHandler(meta, action, propName, value) {
          ///LOGGING
          reporter.state(
              `${infos.instruction_handler_fired} ${action} ${propName}`
          );
          ///END LOGGING
          //if this is internal
          if (constants.internalOnly.indexOf(propName) !== -1) {
              throw new Error(
                  `${errors.statenet.access_instruction_failed_internalonly} (${propName})`
              );
          }
          else if (action === "get") {
              //local instruction property
              if (meta.hasOwnProperty(propName)) {
                  return meta[propName];
              }
              else {
                  return;
              }
          }
          else if (action === "set") {
              if (constants.readOnly.indexOf(propName) !== -1) {
                  throw new Error(
                      `${errors.set_instruction_failed_readonly} (${propName})`
                  );
              }
              meta[instruction] = value;
          }
          throw new Error(
              `${errors.statenet.invalid_op_instruction} (${propName} ${action})`
          );
      }
      /**
      * @function
      */
      function listenerMethodHandler(meta, trapName, propName) {
          if (trapName === "get") {
              //wrap the listener methods to insert the meta namspace on the namespace passed to the handler
              if (
                  propName === "$addListener"
                  || propName === "$hasListener"
                  || propName === "$fireListener"
              ) {
                  return function wrappedListenerMethod(...args) {
                      if (is_array(args[0])) {
                          args[0] = args[0].map(
                              function appendParentNamespace(namespace) {
                                  return `${meta.__namespace}.${namespace}`;
                              }
                          );
                      }
                      else {
                          args[0] = `${meta.__namespace}.${args[0]}`;
                      }
  
                      return listenerManager[propName].apply(null, args);
                  };
              }
              else if (propName === "$removeListener") {
                  return listenerManager[propName];
              }
          }
          throw new Error(
              `${errors.statenet.illegal_listener_operation} (${trapName} ${propName})`
          );
      }
  
      /**
      * @function
      */
      function isInstruction(propName) {
          if (typeof propName === "symbol") {
              return false;
          }
          if (!propName.indexOf) {
              debugger;
          }
          if (
              propName.indexOf("__") === 0
              && constants.instructions.indexOf(propName) !== -1
          ) {
              return true;
          }
          return false;
      }
      /**
      * @function
      */
      function isStateful(value) {
          if (is_objectValue(value) || is_func(value)) {
              return !!value[NamespaceSymbol];
          }
          return false;
      }
      /**
      * @function
      */
      function isAsyncFunction(propName) {
          if (cnsts.asyncFunctionNames.indexOf(propName) !== -1) {
              return true;
          }
          return false;
      }
      /**
      * @function
      */
      function findStateful(obj, key) {
          if (!is_objectValue(obj)) {
              return null;
          }
          //if this has the property but isn't stateful skip prototype checks
          if (obj.hasOwnProperty(key) && !isStateful(obj)) {
              return null;
          }
          //loop through the prototype chain
          while(!isStateful(obj) && !obj.hasOwnProperty(key)) {
              obj = Object.getPrototypeOf(obj);
              if (!obj) {
                  break;
              }
          }
  
          return obj || null;
      }
      /**
      * @function
      */
      function fireListener(meta, eventType, eventDetails) {
          //fire the direct listener
          listenerManager.$fireListener(
              eventDetails.namespace
              , eventType
              , eventDetails
          );
          //loop through each link type, matching the A side for links that match
          //  the event namespace
          cnsts.stateLinkNames
          .forEach(
              function fireLinkTypeListeners(linkType) {
                  fireLinkListeners(
                      meta.stateLinks[linkType]
                      , eventType
                      , eventDetails
                  );
              }
          );
      }
      /**
      * @function
      */
      function fireLinkListeners(links, eventType, eventDetails) {
          links.sideA
          .forEach(
              function findMatchingLinks(linkNamespace, index) {
                  if (eventDetails.namespace.indexOf(linkNamespace) === 0) {
                      var symLinkNamespace = eventDetails.namespace.replace(
                          linkNamespace
                          , links.sideZ[index]
                      );
                      listenerManager.$fireListener(
                          symLinkNamespace
                          , eventType
                          , eventDetails
                      );
                  }
              }
          );
      }
      /**
      * @function
      */
      function fireListenerAsync(meta, eventType, eventDetails) {
          //fire the direct listener
          return listenerManager.$fireListenerAsync(
              eventDetails.namespace
              , eventType
              , eventDetails
          )
          .then(
              function thenFinishResultPromise(result) {
                  if (is_promise(result)) {
                      return result;
                  }
                  return promise.resolve();
              }
          )
          .then(
              function thenFireLinkListener() {
                  return fireLinkListenersAsync(
                      meta
                      , eventType
                      , eventDetails
                  );
              }
          )
      }
      /**
      * @function
      */
      async function fireLinkListenersAsync(meta, eventType, eventDetails) {
          var linkType
          , symLinkNamespace
          , proc = promise.resolve()
          ;
          //loop through the link types
          cnsts.stateLinkNames
          .forEach(
              function fireLinkTypeListeners(linkType) {
                  //loop through the side A of this type
                  meta.stateLinks[linkType]
                  .sideA
                  .forEach(
                      function fireEachLinkListener(link) {
                          //create the namespace for the z side of the link
                          var symLinkNamespace = eventDetails.namespace.replace(
                              linkNamespace
                              , links.sideZ[index]
                          );
                          //add the listener firing to the process chain
                          proc = proc.then(
                              function thenFireNextListener() {
                                  return listenerManager.$fireListenerAsync(
                                      symLinkNamespace
                                      , eventType
                                      , eventDetails
                                  );
                              }
                          );
                      }
                  );
              }
          );
  
          return proc;
      }
  
      /**
      * @function
      */
      function parseNamespace(namespace) {
          var parts = namespace
          .split(DOT_PATT)
          , name = parts.pop()
          , parentNamespace = parts.join(".")
          ;
  
          return [
              parentNamespace
              , name
          ];
      }
      /**
      * @function
      */
      function getNamespace(meta, propName) {
          return !!meta.__namespace
          ? `${meta.__namespace}.${propName}`
          : propName
          ;
      }
      /**
      * @function
      */
      function cleanNamespace(linkPath) {
          return linkPath.indexOf("$.") === 0
              ? linkPath.substring(2)
              : linkPath
          ;
      }
  }