docs: function objectCreateComputedProp(obj, prop, setter, enumerable = true) {
      let propValue;
      let newValue;
      let needsInitialization = true;
      let allowSet = false;
      let needsNewValue = true;
      let isGeneratingNewValue = false;
  
      const dependencyTracker = () => {
          if (needsNewValue) {
              return;
          }
  
          needsNewValue = true;
  
          // If we have watchers on this computed prop, then queue the
          // value generator function.
          // else, just notify dependents.
          if (alwaysForceExec || setter.forceExec || obj[OBSERVABLE_IDENTIFIER].props[prop].watchers.size) {
              nextTick.queue(setPropValue);
          }
          else if (obj[OBSERVABLE_IDENTIFIER].props[prop].dependents.size) {
              obj[OBSERVABLE_IDENTIFIER].props[prop].dependents.notify();
          }
      };
  
      const setPropValue = silentSet => {
          // if there is no longer a need to regenerate the value, exit.
          // this can happen when other logic accesses the computed getter
          // between scheduled updates.
          // Also, in order to avoid looping, if value is currently being
          // generated, then also exit.
          if (!needsNewValue || isGeneratingNewValue) {
              return;
          }
  
          isGeneratingNewValue = true;
  
          try {
              setDependencyTracker(dependencyTracker);
              newValue = setter.call(obj, obj);
              unsetDependencyTracker(dependencyTracker); // IMPORTANT: turn if off right after setter is run!
  
              if (silentSet) {
                  propValue = newValue;
  
                  if (obj[OBSERVABLE_IDENTIFIER].props[prop].deep) {
                      makeObservable(propValue);
                  }
              } else {
                  // Update is done via the prop assignment, which means that
                  // handing of `deep` and all dependent/watcher notifiers is handled
                  // as part of the objectWatchProp() functionality.
                  // Doing the update this way also supports the use of these
                  // objects with other library that may also intercept getter/setters.
                  allowSet = true;
                  needsNewValue = false;
                  obj[prop] = newValue;
              }
          } catch (e) {
              allowSet = needsNewValue = isGeneratingNewValue = false;
              newValue = undefined;
              unsetDependencyTracker(dependencyTracker);
              throw e;
          }
  
          allowSet = needsNewValue = isGeneratingNewValue = false;
          newValue = undefined;
      };
  
      dependencyTracker.asDependent = true;
      dependencyTracker.forProp = setPropValue.forProp = prop;
  
      // Does property already exists? Delete it.
      if (prop in obj) {
          delete obj[prop];
  
          // Was prop an observable? if so, signal that interceptors must be redefined.
          if (obj[OBSERVABLE_IDENTIFIER] && obj[OBSERVABLE_IDENTIFIER].props[prop]) {
              obj[OBSERVABLE_IDENTIFIER].props[prop].setupInterceptors = true;
          }
      }
  
      defineProperty(
          obj,
          prop,
          undefined,
          function(){
              if (needsInitialization) {
                  needsInitialization = false;
                  setPropValue(true);
              }
              else if (needsNewValue) {
                  setPropValue();
              }
  
              return propValue;
          },
          function () {
              if (allowSet) {
                  propValue = newValue;
              }
              return propValue;
          },
          true,
          !!enumerable
      );
  
      objectWatchProp(obj, prop);
  }