Re: [IndexedDB] Computed indexes

On Sat, Jun 19, 2010 at 1:05 AM, Jonas Sicking <jonas@sicking.cc> wrote:
>> Maybe we could make
>> the global scope be empty when compiling (so variables can't be bound) and
>> executing the function?
>
> Yes, we absolutely should. Forgot to mention this.
>
>> What is the difference between an "expressionIndex" and a keyPath?  It seems
>> like they're doing about the same thing.  My proposal to allow keyPath to be
>> artibrary JavaScript and then have the value being inserted be the global
>> scope actually sounds almost identical to what you're doing....except more
>> in the relm of what JS engines already do (since it's much like an eval).
>
> It is about the same thing yes. Though presumably an implementation
> could optimize "evaluating" the keyPath heavily. Much more so than a
> generic expression.
>
> Allowing keyPath to be an arbitrary expression turns out to result in
> weird edge cases once you define all details. Say that you're storing
> the value:
>
> { foo: 5, bar: 10 }
>
> You want to evaluate the expression in a context where "foo" and "bar"
> are in scope. But you also don't want to evaluate with the value as
> the global object as then "a = 5" would modify the value as that sets
> a global variable. I.e. something like "t = foo*foo; bar + t;" would
> add a 't' property to value. And you also don't want to evaluate the
> expression in a context where the value is the current scope as then
> "var a = 5" would modify the value.
>
> Additionally, you have to define what value is returned. We could do
> like 'eval' is doing and say that the last evaluated expression is
> what is returned. However eval doesn't let you return early using the
> 'return' statement which might be practical.
>
> These problems could possibly be overcome though. I'll have to check
> with people that know JS better than me. Ideas welcome.

I talked to some javascript Gurus here and came up with this proposal:

The string passed in is passed to the javascript Function constructor
in the following manner:

f = new Function("value", passedInExpressionString);
Object.freeze(f);

The resulting function is then executed for each value in the object
store, and the returned value is used as key in the index. If the
returned value is undefined, or if an exception is thrown, no entry is
added to the index. The function is executed in a global scope which
also is frozenand has no available properties other than the ones
defined by the ECMAScript standard. I.e. things like document,
XMLHttpRequest and setTimeout is not available.

Here are some example expressions:
Index on the result of adding two properties together:
"return value.a + value.b;"

Index on the number of days between two dates:
"return (value.to - value.from) / 1000*60*60*24;"

Index on a persons last name:
"var names = value.name.split(/\\s*/); return names[names.length - 1];"

The reason to freeze the global object and the function is to prevent
the expression from retaining state from one execution to the next. We
could also say that a fresh function object and a fresh global scope
object is created, however that would result in slower execution.

/ Jonas

Received on Wednesday, 23 June 2010 23:12:29 UTC