`DOpus.TypeOf()` throws!

var v = DOpus.vars("nonexistentVariable");
DOpus.Output(typeof v); // `object`
DOpus.Output(DOpus.TypeOf(v)); // `object` - Shouldn't this be `object.Var`?
DOpus.Output(DOpus.TypeOf({})); // `object` - Really the same kind?
DOpus.Output(typeof v.value); // `unknown`
DOpus.Output(DOpus.TypeOf(v.value)); // Throws! Should never happen.

It would be nice to be able to use the Var object itself to check for variable existence instead of having to mention the variable name twice: first in vars.Exists(), then fetching its Var object from the collection. I'd like to fetch the Var object that way, ensure it's associated with an existing variable, read it, and delete it. If proper behavior of DOpus.TypeOf() can't tell me whether the variable exists, how about an additional exists property in Var?

Vars.Exists() tells you if a variable exists or not.

I obviously knew that.

And var.value as well as vars.Get() tell you a variable's value.

Since you already get a Var object for non-existent variables (whose name property can be correctly queried, e.g.), why not also have exists, if it's technically feasible?

Currently only possible:

var output = null;
if (DOpus.vars.Exists("myVariableBlaBlaBlaYadaYadaYada")) {
    var variable = DOpus.vars("myVariableBlaBlaBlaYadaYadaYada");
    output = variable.value;
    variable.Delete();
}

With exists property:

var output = null;
var variable = DOpus.vars("myVariableBlaBlaBlaYadaYadaYada");
if (variable.exists) {
    output = variable.value;
    variable.Delete();
}

But irrespective of my preferences regarding variable existence checks, DOpus.TypeOf() should never throw, no matter the circumstances. Just image JScript's typeof operator throwing.

DOpus.TypeOf isn't what's throwing. You're trying to access v.value which is an invalid property if v doesn't exist, and that's what's throwing.

Nothing is wrong here except your code.

You're right. That COM stuff where mere property access may throw was a little irritating to me. I expected for typesof v.value to throw also, if accessing value threw. But I guess that's the same as with checking for never-declared variables using typeof neverDeclared === "undefined", which also doesn't throw.

So, there is an alternative to vars.Exists():

var output = null;
var variable = DOpus.vars("myVariableBlaBlaBlaYadaYadaYada");
try {
    output = variable.value;
} catch (e) { }
variable.Delete();

I prefer this over mentioning the variable name twice, which would also mean needing to use more find-and-replace or editing multiple locations for refactoring. But I'd prefer .exists over this, if it would be provided.

That looks horrendous to me, and would perform much worse as well.

Why not just use things the way they were designed to be used?

To me it looks better. Isn't it that try-catch only performs worse in the case of exceptions in fact being thrown? The non-existence case is the anomaly with my code - an exception.

Having had a look into this:

  • DOpus.vars will return a Var object, even for non-existent variables; you can create the variable by assigning to the object's value property.
  • It is incorrect that DOpus.TypeOf(v) only returns "object" - it should return "object.Var". We'll fix that.
  • I'm not sure what type of object {} creates in JScript; I guess an array? But it's not an Opus object so DOpus.TypeOf has no idea what it is.
  • If a Var references a non-existent variable, attempting to read from value will return an ActiveScripting error - DISP_E_UNKNOWNNAME (this is the "throwing" you refer to).
  • JScript's typeof operator is obviously able to suppress the error and returns "unknown".
  • DOpus.TypeOf() isn't even being called in this situation - the reference to v.value returns the error and the script aborts at that point, without even calling into the TypeOf method.
  • It turns out the Var object does actually have an exists property, but this was omitted from the documentation.
3 Likes

I can't reproduce this positively (DOpus v13.14):

var v = DOpus.vars("nonexistentVariable");

// `unknown`
DOpus.Output(typeof v.exists);

// Throws: "A method was called unexpectedly".
// BTW: Could this exception message in general not say "method"?
DOpus.Output(String(v.exists));

It's the same output and exception message with this:

DOpus.vars.Set("existentVariable", 123);
var v = DOpus.vars("existentVariable");

DOpus.Output(typeof v.exists);
DOpus.Output(String(v.exists));

The newly published docs to the exists property say:

When you index the Vars object by name, it will return a Var object event for non-existent values.

Why is it said that an "event" is returned? The "Return Type" column says "bool".