Commit 16155100 authored by Leon Arnott's avatar Leon Arnott
Browse files

Fixed two bugs.

 * Fixed a long-standing bug where line breaks couldn't be used as whitespace around operators.
 * Fixed a bug where bind and 2bind wouldn't work properly when the bound variable was a data structure name (such as "bind $list's 1st").
parent 28b11094f335
......@@ -6,6 +6,8 @@ Documentation is at http://twine2.neocities.org/. See below for compilation inst
#### Bugfixes
* Fixed a long-standing bug where line breaks couldn't be used as whitespace around operators. For instance, `(print: 2`, a line break, then `is > 1)` would cause an error instead of being treated as `(print: 2 is > 1)`.
* Fixed a bug where `bind` and `2bind` wouldn't work properly when used to bind a data structure's data name (such as `bind $list's 1st`).
* Fixed a bug where error messages would incorrectly call custom macros' parameters "a number" even if that parameter was restricted to something else.
* Fixed a code generation bug in the "The passage ___ was visited" option of the "If" pane of the editor toolbar.
......
......@@ -239,10 +239,7 @@ define(['state', 'internaltypes/twineerror', 'utils', 'utils/operationutils', 'd
return arr;
},[]);
return {
compiledPropertyChain,
deepestObject: object,
};
return compiledPropertyChain;
}
/*
......@@ -681,7 +678,9 @@ define(['state', 'internaltypes/twineerror', 'utils', 'utils/operationutils', 'd
if (this.error) {
return this.error;
}
return get(this.deepestObject, this.compiledPropertyChain.slice(-1)[0],
const deepestObject = this.compiledPropertyChain.slice(0,-1).reduce((deepestObject, prop) => get(deepestObject, prop), this.object);
return get(deepestObject, this.compiledPropertyChain.slice(-1)[0],
/*
This is the original non-computed property. It is used only for
the error message when no property is found.
......@@ -1026,8 +1025,8 @@ define(['state', 'internaltypes/twineerror', 'utils', 'utils/operationutils', 'd
/*
If the passed-in object is a TypedVar, expand the propertyChain
*/
const {compiledPropertyChain, deepestObject} = compilePropertyChain(object, propertyChain);
if ((error = TwineError.containsError(compiledPropertyChain, deepestObject))) {
const compiledPropertyChain = compilePropertyChain(object, propertyChain);
if ((error = TwineError.containsError(compiledPropertyChain))) {
return wrapError(error);
}
......@@ -1035,7 +1034,7 @@ define(['state', 'internaltypes/twineerror', 'utils', 'utils/operationutils', 'd
Create the VarRefProto instance.
*/
return Object.assign(Object.create(VarRefProto), {
object, propertyChain, compiledPropertyChain, deepestObject
object, propertyChain, compiledPropertyChain
});
},
......
......@@ -456,7 +456,9 @@
anyLetter,
anyLetterStrict,
whitespace: mws,
// This is used only for macroMode, NOT markup modes.
whitespace:
mws.replace("[","[\\n\\r"),
/*d:
Escaped line break markup
......
......@@ -172,6 +172,15 @@ describe("interface macros", function(){
done();
},20);
});
it("works with bound data structure properties", function(done) {
var p = runPassage("(set:$foo to (a:'baz'))("+name+": 2bind $foo's 1st, 'bar','baz', 'qux')(link:'X')[(set:$foo's 1st to 'bar')]");
expect(p.find('tw-expression[name='+name+'] tw-link').text()).toBe('baz');
p.find('tw-hook tw-link').click();
setTimeout(function(){
expect(p.find('tw-expression[name='+name+'] tw-link').text()).toBe("bar");
done();
},20);
});
});
it("errors if the bind is invalid", function() {
expect("(set:$foo to 1)("+name+": bind $foo's 1st, 'bar','baz', 'qux')").markupToError();
......@@ -434,6 +443,14 @@ describe("interface macros", function(){
done();
},20);
});
it("if two-way-bound, updates the <textarea> when the bound data structure property updates", function(done) {
var p = runPassage("(set:$foo to (dm:'qux','Quux'))("+name+":2bind $foo's qux, \"XXX===\",3,'Foo')(link:'X')[(set:$foo to (dm:'qux','Baz'))]");
p.find('tw-hook tw-link').click();
setTimeout(function(){
expect(p.find('textarea').val()).toBe("Baz");
done();
},20);
});
}
else {
it("when text is input, its characters are changed to those of the provided string", function() {
......@@ -656,18 +673,30 @@ describe("interface macros", function(){
/*
TODO: center meter tests
*/
it("updates the bar when the variable updates", function() {
it("updates the bar when the bound variable updates", function() {
var p = runPassage("(set:$foo to 10)(meter: bind $foo, 100, '=X', 'Yo')(link:'baz')[(set:$foo to 90)]");
expect(p.find('tw-meter').css('background-size')).toBe('10%');
p.find('tw-link').click();
expect(p.find('tw-meter').css('background-size')).toBe('90%');
});
it("updates the text when the variable updates", function() {
it("updates the text when the bound variable updates", function() {
var p = runPassage("(set:$foo to 10)(meter: bind $foo, 100, '=X', 'FOO: $foo')(link:'baz')[(set:$foo to 90)]");
expect(p.find('tw-meter').text()).toBe('FOO: 10');
p.find('tw-link').click();
expect(p.find('tw-meter').text()).toBe('FOO: 90');
});
it("updates the bar when the bound data structure property updates", function() {
var p = runPassage("(set:$foo to (dm:'baz',10))(meter: bind $foo's baz, 100, '=X', 'Yo')(link:'baz')[(set:$foo's baz to 90)]");
expect(p.find('tw-meter').css('background-size')).toBe('10%');
p.find('tw-link').click();
expect(p.find('tw-meter').css('background-size')).toBe('90%');
});
it("updates the text when the bound data structure property updates", function() {
var p = runPassage("(set:$foo to (dm:'baz',10))(meter: bind $foo's baz, 100, '=X', 'FOO: (print:$foo\\'s baz)')(link:'baz')[(set:$foo's baz to 90)]");
expect(p.find('tw-meter').text()).toBe('FOO: 10');
p.find('tw-link').click();
expect(p.find('tw-meter').text()).toBe('FOO: 90');
});
it("gives the <tw-expression> the specified margins, width, and rows (if given), as well as display:block", function() {
[
['=XX=', 25, 50],
......
......@@ -12,6 +12,8 @@ describe("macro calls", function() {
expect("(a: \n )").markupToPrint("");
expect("(a:\n1 )").markupToPrint("1");
expect("(a:\n 1\n ,\n 1\n )").markupToPrint("1,1");
expect("(a:\n\t1\n\t,\n\t1\n\t)").markupToPrint("1,1");
expect("(print:2\nis 2)").markupToPrint("true");
});
it("cannot have whitespace between the name and :", function() {
expect("(a : )").markupToPrint("(a : )");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment