Skip to content

Commit

Permalink
Fix bug with function inside with block
Browse files Browse the repository at this point in the history
  • Loading branch information
nilproject committed Mar 5, 2017
1 parent e75ef6a commit b6c2146
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 67 deletions.
7 changes: 7 additions & 0 deletions FunctionalTests/FunctionInsideWith.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
with ({ a: 'hello' }) {
function f() {
(function () { })(a);
}

f();
}
1 change: 1 addition & 0 deletions FunctionalTests/FunctionalTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<Content Include="Array\includes.js" />
<Content Include="Array\findIndex.js" />
<Content Include="flow control tests.js" />
<Content Include="FunctionInsideWith.js" />
<Content Include="fuzz.js" />
<Content Include="Generated\Embedded.tt">
<Generator>TextTemplatingFileGenerator</Generator>
Expand Down
52 changes: 28 additions & 24 deletions FunctionalTests/Generated/Embedded.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,55 @@ namespace NiL.JS.Test.Generated
public sealed class EmbeddedTests : FileTestBase
{
[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\flow control tests.js"
public void flow_control_tests_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\flow control tests.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\flow control tests.js"
public void flow_control_tests_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\flow control tests.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\fuzz.js"
public void fuzz_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\fuzz.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\FunctionInsideWith.js"
public void FunctionInsideWith_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\FunctionInsideWith.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\infinity test.js"
public void infinity_test_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\infinity test.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\fuzz.js"
public void fuzz_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\fuzz.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Int16Array.js"
public void Int16Array_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Int16Array.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\infinity test.js"
public void infinity_test_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\infinity test.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Int8Array.js"
public void Int8Array_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Int8Array.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Int16Array.js"
public void Int16Array_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Int16Array.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\md5.js"
public void md5_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\md5.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Int8Array.js"
public void Int8Array_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Int8Array.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\new functions of Object.js"
public void new_functions_of_Object_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\new functions of Object.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\md5.js"
public void md5_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\md5.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\this linking test.js"
public void this_linking_test_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\this linking test.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\new functions of Object.js"
public void new_functions_of_Object_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\new functions of Object.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\entries.js"
public void Array_entries_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\entries.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\this linking test.js"
public void this_linking_test_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\this linking test.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\find.js"
public void Array_find_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\find.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\entries.js"
public void Array_entries_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\entries.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\findIndex.js"
public void Array_findIndex_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\findIndex.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\find.js"
public void Array_find_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\find.js");

[TestMethod]
#line 1 "C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\includes.js"
public void Array_includes_js() => RunFile(@"C:\Users\dpolhovich\Desktop\repo\NiL.JS\FunctionalTests\Array\includes.js");
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\findIndex.js"
public void Array_findIndex_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\findIndex.js");

[TestMethod]
#line 1 "C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\includes.js"
public void Array_includes_js() => RunFile(@"C:\Users\Дмитрий\Documents\Visual Studio 2015\Projects\NiL.JS\FunctionalTests\Array\includes.js");
}
}
15 changes: 9 additions & 6 deletions NiL.JS/Expressions/FunctionDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -762,13 +762,16 @@ public override void RebuildScope(FunctionInfo functionInfo, Dictionary<string,
{
base.RebuildScope(functionInfo, null, scopeBias);

var tv = _functionInfo.WithLexicalEnvironment ? null : new Dictionary<string, VariableDescriptor>();
_body.RebuildScope(_functionInfo, tv, scopeBias + (_body._variables == null || _body._variables.Length == 0 || !_functionInfo.WithLexicalEnvironment ? 1 : 0));
if (tv != null)
var tempVariables = _functionInfo.WithLexicalEnvironment ? null : new Dictionary<string, VariableDescriptor>();
_body.RebuildScope(_functionInfo, tempVariables, scopeBias + (_body._variables == null || _body._variables.Length == 0 || !_functionInfo.WithLexicalEnvironment ? 1 : 0));
if (tempVariables != null)
{
var vars = new List<VariableDescriptor>(tv.Values);
vars.RemoveAll(x => x is ParameterDescriptor);
_body._variables = vars.ToArray();
var block = _body as CodeBlock;
if (block != null)
{
block._variables = tempVariables.Values.Where(x => !(x is ParameterDescriptor)).ToArray();
block.suppressScopeIsolation = SuppressScopeIsolationMode.DoNotSuppress;
}
}
}

Expand Down
29 changes: 20 additions & 9 deletions NiL.JS/Statements/CodeBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,17 +187,11 @@ internal static CodeNode Parse(ParseInfo state, ref int index)

expectSemicolon = false;
}

continue;
}

if (t is EntityDefinition)
{
expectSemicolon = false;
}
else
{
expectSemicolon = true;
}
expectSemicolon = !(t is EntityDefinition);

body.Add(t);
}
Expand All @@ -212,8 +206,10 @@ internal static CodeNode Parse(ParseInfo state, ref int index)
state.functionScopeLevel = oldFunctionScopeLevel;
state.lexicalScopeLevel--;
}

if (!sroot)
position++;

int startPos = index;
index = position;
return new CodeBlock(body.ToArray())
Expand All @@ -238,12 +234,14 @@ internal static VariableDescriptor[] extractVariables(ParseInfo state, int oldVa
if (state.Variables[i].definitionScopeLevel == state.lexicalScopeLevel)
count++;
}

if (count > 0)
{
variables = new VariableDescriptor[count];
HashSet<string> declaredVariables = null;
if (state.lexicalScopeLevel != state.functionScopeLevel)
declaredVariables = new HashSet<string>();

for (int i = oldVariablesCount, targetIndex = 0; i < state.Variables.Count; i++)
{
if (state.Variables[i].definitionScopeLevel == state.lexicalScopeLevel)
Expand All @@ -252,7 +250,7 @@ internal static VariableDescriptor[] extractVariables(ParseInfo state, int oldVa
if (declaredVariables != null)
{
if (declaredVariables.Contains(variables[targetIndex].name) && variables[targetIndex].lexicalScope)
ExceptionHelper.ThrowSyntaxError("Variable \"" + variables[targetIndex].name + "\" has already been defined", state.Code, i);
ExceptionHelper.ThrowSyntaxError("Variable \"" + variables[targetIndex].name + "\" already has been defined", state.Code, i);

declaredVariables.Add(variables[targetIndex].name);
}
Expand All @@ -263,6 +261,7 @@ internal static VariableDescriptor[] extractVariables(ParseInfo state, int oldVa
state.Variables[i - targetIndex] = state.Variables[i];
}
}

state.Variables.RemoveRange(state.Variables.Count - count, count);
}

Expand Down Expand Up @@ -407,8 +406,10 @@ protected internal override CodeNode[] getChildsImpl()
break;
res.Add(node);
}

if (_variables != null)
res.AddRange(from v in _variables where v.initializer != null && (!(v.initializer is FunctionDefinition) || (v.initializer as FunctionDefinition)._body != this) select v.initializer);

return res.ToArray();
}

Expand Down Expand Up @@ -514,6 +515,7 @@ public override bool Build(ref CodeNode _this, int expressionDepth, Dictionary<s
compiledVersion = JITHelpers.compile(this, depth >= 0);
#endif
}

if (t >= 0 && this == _this)
{
var newBody = new CodeNode[_lines.Length - t - 1];
Expand All @@ -522,20 +524,23 @@ public override bool Build(ref CodeNode _this, int expressionDepth, Dictionary<s
newBody[f++] = _lines[t];
_lines = newBody;
}

if (_variables != null && _variables.Length != 0)
{
for (var i = 0; i < _variables.Length; i++)
{
variables.Remove(_variables[i].name);
}
}

if (variablesToRestore != null)
{
for (var i = 0; i < variablesToRestore.Count; i++)
{
variables[variablesToRestore[i].name] = variablesToRestore[i];
}
}

return false;
}

Expand Down Expand Up @@ -563,12 +568,14 @@ public override void Optimize(ref CodeNode _this, FunctionDefinition owner, Comp
}
}
}

for (int i = 0; i < _lines.Length; i++)
{
var cn = _lines[i] as CodeNode;
cn.Optimize(ref cn, owner, message, opts, stats);
_lines[i] = cn;
}

if (_variables != null)
{
for (var i = 0; i < _variables.Length; i++)
Expand All @@ -583,6 +590,9 @@ public override void Optimize(ref CodeNode _this, FunctionDefinition owner, Comp

if (_lines.Length == 1 && suppressScopeIsolation == SuppressScopeIsolationMode.Suppress)
{
if (_variables.Length != 0)
throw new InvalidOperationException();

_this = _lines[0];
}
}
Expand Down Expand Up @@ -620,6 +630,7 @@ public override void RebuildScope(FunctionInfo functionInfo, Dictionary<string,
if (!transferedVariables.TryGetValue(_variables[i].name, out desc) || _variables[i].initializer != null)
transferedVariables[_variables[i].name] = _variables[i];
}

_variables = emptyVariables;
}

Expand Down
Loading

0 comments on commit b6c2146

Please sign in to comment.