Closed Bug 883664 Opened 13 years ago Closed 13 years ago

Unify how compiler reacts to missing members of strings, hashes, globals and variables

Categories

(L20n :: JS Library, defect, P1)

x86_64
Linux
defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: stas, Assigned: stas)

References

Details

Let's look at some code samples and the current compiler's behavior: A. <foo['a', 'b'] "Foo"> <bar['a', 'b'] { *one: "One", two: "Two" }> Output: foo Foo bar One In foo, the compiler doesn't even look at 'a' or 'b' in the index, because the value is a string. In bar, the compiler doesn't look at 'b', because the hash is only one-level-deep. B. <string1 "{{ foo.x }}"> <string2 "{{ foo.x.y }}"> <string3 "{{ foo.x.y.z }}"> Output: string1 Foo string2 {{ foo.x.y }} (ValueError in string2: y is not defined in the context data) string3 {{ foo.x.y.z }} (ValueError in string3: y is not defined in the context data) foo.x in string1 behaves a bit like an index in that it tries to get the 'x' member, fails, and returns the value Foo. But foo.x.y and foo.x.y.z are inconsistent with the index behavior and throw. C. <hash1 "{{ bar.one.x }}"> hash1 One bar.one is a string, so bar.one.x works the same as foo.x above: it falls back on the value of bar.one (One) <hash2 "{{ bar.one.x.y }}"> hash2 {{ bar.one.x.y }} (ValueError in hash2: y is not defined in the context data) Same as foo.x.y <hash3 "{{ bar.x }}"> hash3 One This one is interesting. x is not found in bar's keys, so the default key is used: one. So bar.x is the same as bar.one, i.e. One. <hash4 "{{ bar.x.y }}"> hash4 One As seen above, bar.x is the same as bar.one, and is a string. Thus, bar.x.y works the same way as foo.x: <string>.<missing property> and it falls back on the value of the string. <hash5 "{{ bar.x.y.z }}"> hash5 {{ bar.x.y.z }} (ValueError in hash5: z is not defined in the context data) Only now does the compiler fail, similar to foo.x.y. * * * 1. Should indexes be treated the same as property expressions? I think it's OK for them to not behave the same way. Indexes are declarative, while property expressions are imperative. We don't even have to look at the index to return the value. 2. Should string.property fall back gracefully on the value of the string, or fail? I'd like to suggest a change in that the compiler should fail in these scenarios. <string1 "{{ foo.x }}"> <string2 "{{ foo.x.y }}"> <string3 "{{ foo.x.y.z }}"> string{1,2,3} should all fail with "x is not defined". The same should happen for globals and variables if the requested property is not found. <global "{{ @foo.x }}"> should fail with "x is not defined" if @foo is a string or an object without a member called x. <variable "{{ $foo.x }}"> should fail with "x is not defined" if $foo is a string or an object without a member called x.
Assignee: nobody → stas
Priority: -- → P1
QA Contact: gandalf
Target Milestone: --- → 1.0
That sounds good
Depends on: 881646
Blocks: 815962
Landed in https://github.com/l20n/l20n.js/commit/4df76aab0c49fe09eead9d54b77b94e36dd1f218 There are many changes in the patch, mostly tests and some clean-up regarding Runtime errors in compiler.js. The beef of the fix is in PropertyExpression: https://github.com/l20n/l20n.js/commit/4df76aab0c49fe09eead9d54b77b94e36dd1f218#L0R822 The patch adds 72 tests (8 of which pending bug 816887 and bug 884734) - I think this fix will also greatly help with bug 815962. I tried to make sure I'm careful with built-in properties like 'length' on a string (which is an own property).
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.