Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

17-05 ChakraCore servicing release #2959

Merged
merged 12 commits into from
May 12, 2017
Merged
9 changes: 7 additions & 2 deletions lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7095,12 +7095,15 @@ ParseNodePtr Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, uin

ArenaAllocator tempAllocator(_u("ClassMemberNames"), m_nodeAllocator.GetPageAllocator(), Parser::OutOfMemory);

size_t cbMinConstructor = 0;
ParseNodePtr pnodeClass = nullptr;
if (buildAST)
{
pnodeClass = CreateNode(knopClassDecl);

CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT(Class, m_scriptContext);

cbMinConstructor = m_pscan->IecpMinTok();
}

m_pscan->Scan();
Expand Down Expand Up @@ -7393,9 +7396,11 @@ ParseNodePtr Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, uin
}
}

size_t cbLimConstructor = 0;
if (buildAST)
{
pnodeClass->ichLim = m_pscan->IchLimTok();
cbLimConstructor = m_pscan->IecpLimTok();
}

if (!hasConstructor)
Expand Down Expand Up @@ -7430,8 +7435,8 @@ ParseNodePtr Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, uin

if (buildAST)
{
pnodeConstructor->sxFnc.cbMin = pnodeClass->ichMin;
pnodeConstructor->sxFnc.cbLim = pnodeClass->ichLim;
pnodeConstructor->sxFnc.cbMin = cbMinConstructor;
pnodeConstructor->sxFnc.cbLim = cbLimConstructor;
pnodeConstructor->ichMin = pnodeClass->ichMin;
pnodeConstructor->ichLim = pnodeClass->ichLim;

Expand Down
9 changes: 8 additions & 1 deletion lib/Runtime/Library/ScriptFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,14 @@ namespace Js
LPCUTF8 pbStart = pFuncBody->GetSource(_u("ScriptFunction::EnsureSourceString"));
BufferStringBuilder builder(cch, scriptContext);
utf8::DecodeOptions options = pFuncBody->GetUtf8SourceInfo()->IsCesu8() ? utf8::doAllowThreeByteSurrogates : utf8::doDefault;
utf8::DecodeUnitsInto(builder.DangerousGetWritableBuffer(), pbStart, pbStart + cbLength, options);
size_t decodedCount = utf8::DecodeUnitsInto(builder.DangerousGetWritableBuffer(), pbStart, pbStart + cbLength, options);

if (decodedCount != cch)
{
AssertMsg(false, "Decoded incorrect number of characters for function body");
Js::Throw::FatalInternalError();
}

if (pFuncBody->IsLambda() || isActiveScript || this->GetFunctionInfo()->IsClassConstructor()
#ifdef ENABLE_PROJECTION
|| scriptContext->GetConfig()->IsWinRTEnabled()
Expand Down
53 changes: 53 additions & 0 deletions test/utf8/bugGH2656.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");

var tests = [
{
name: "Serialize functions with unicode sequences",
body: function () {
assert.areEqual('function foo() { /* 𢭃 */ }', '' + function foo() { /* 𢭃 */ }, 'Serialized function declaration produces correct string in presense of multi-byte unicode characters');
assert.areEqual('function 𢭃() { /* 𢭃 */ }', '' + function 𢭃() { /* 𢭃 */ }, 'Serialized function with a unicode identifier');
assert.areEqual('function 𢭃(ā,食) { /* 𢭃 */ }', '' + function 𢭃(ā,食) { /* 𢭃 */ }, 'Serialized function with a unicode identifier and unicode argument list');

assert.areEqual('async function foo() { /* 𢭃 */ }', '' + async function foo() { /* 𢭃 */ }, 'Serialized async function declaration produces correct string in presense of multi-byte unicode characters');
assert.areEqual('async function 𢭃() { /* 𢭃 */ }', '' + async function 𢭃() { /* 𢭃 */ }, 'Serialized async function with a unicode identifier');
assert.areEqual('async function 𢭃(ā,食) { /* 𢭃 */ }', '' + async function 𢭃(ā,食) { /* 𢭃 */ }, 'Serialized async function with a unicode identifier and unicode argument list');

assert.areEqual('function* foo() { /* 𢭃 */ }', '' + function* foo() { /* 𢭃 */ }, 'Serialized generator function declaration produces correct string in presense of multi-byte unicode characters');
assert.areEqual('function* 𢭃() { /* 𢭃 */ }', '' + function* 𢭃() { /* 𢭃 */ }, 'Serialized generator function with a unicode identifier');
assert.areEqual('function* 𢭃(ā,食) { /* 𢭃 */ }', '' + function* 𢭃(ā,食) { /* 𢭃 */ }, 'Serialized generator function with a unicode identifier and unicode argument list');

assert.areEqual('() => { /* 𢭃 */ }', '' + (() => { /* 𢭃 */ }), 'Serialized arrow function declaration produces correct string in presense of multi-byte unicode characters');
assert.areEqual('(ā,食) => { /* 𢭃 */ }', '' + ((ā,食) => { /* 𢭃 */ }), 'Serialized arrow function declaration with a unicode argument list');

assert.areEqual('async () => { /* 𢭃 */ }', '' + (async () => { /* 𢭃 */ }), 'Serialized async arrow function declaration produces correct string in presense of multi-byte unicode characters');
assert.areEqual('async (ā,食) => { /* 𢭃 */ }', '' + (async (ā,食) => { /* 𢭃 */ }), 'Serialized async arrow function declaration with a unicode argument list');
}
},
{
name: "Serialize classes with unicode sequences",
body: function () {
assert.areEqual('class 𢭃 { /* 𢭃 */ }', '' + class 𢭃 { /* 𢭃 */ }, 'Serialized class declaration produces correct string in presense of multi-byte unicode characters');

class ā { 𢭃(物) { /* 𢭃 */ } static 飲(物) { /* 𢭃 */ } async 知(物) { /* 𢭃 */ } static async 愛(物) { /* 𢭃 */ } *泳(物) { /* 𢭃 */ } static *赤(物) { /* 𢭃 */ } get 青() { /* 𢭃 */ } set 緑(物) { /* 𢭃 */ } }

assert.areEqual(
'class ā { 𢭃(物) { /* 𢭃 */ } static 飲(物) { /* 𢭃 */ } async 知(物) { /* 𢭃 */ } static async 愛(物) { /* 𢭃 */ } *泳(物) { /* 𢭃 */ } static *赤(物) { /* 𢭃 */ } get 青() { /* 𢭃 */ } set 緑(物) { /* 𢭃 */ } }',
'' + ā,
'Serialized class with different types of members');

class 食 extends ā { 母(物) { /* 𢭃 */ } static 父(物) { /* 𢭃 */ } async 妹(物) { /* 𢭃 */ } static async 姉(物) { /* 𢭃 */ } *兄(物) { /* 𢭃 */ } static *耳(物) { /* 𢭃 */ } get 明() { /* 𢭃 */ } set 日(物) { /* 𢭃 */ } }

assert.areEqual(
`class 食 extends ā { 母(物) { /* 𢭃 */ } static 父(物) { /* 𢭃 */ } async 妹(物) { /* 𢭃 */ } static async 姉(物) { /* 𢭃 */ } *兄(物) { /* 𢭃 */ } static *耳(物) { /* 𢭃 */ } get 明() { /* 𢭃 */ } set 日(物) { /* 𢭃 */ } }`,
'' + 食,
'Serialized class with an extends clause');
}
},
];

testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });
6 changes: 6 additions & 0 deletions test/utf8/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@
<compile-flags>-forceserialized -oopjit-</compile-flags>
</default>
</test>
<test>
<default>
<files>bugGH2656.js</files>
<compile-flags>-args summary</compile-flags>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is -endargs needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. this test is actually failing the CI.
/cc @boingoing

</default>
</test>
</regress-exe>