Skip to content

Commit

Permalink
[MERGE #5584 @yullin-ms] implement Array.prototype.forEach in javascript
Browse files Browse the repository at this point in the history
Merge pull request #5584 from pr/yullin/forEachJS

Fixes OS: 18004206
implement array.prototype.forEach as JsBuiltIns.
  • Loading branch information
yullin-ms committed Aug 24, 2018
2 parents 7f24991 + 1545cd0 commit 9fdbe23
Show file tree
Hide file tree
Showing 10 changed files with 3,136 additions and 2,787 deletions.
6 changes: 5 additions & 1 deletion lib/Runtime/Language/amd64/amd64_Thunks.S
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,13 @@ NESTED_ENTRY _ZN2Js23AsmJsExternalEntryPointEPNS_16RecyclableObjectENS_8CallInfo
lea rbp, [rsp]

set_cfa_register rbp, (2*8) // Set to compute CFA as: rbp + 16 (sizeof: [rbp] [ReturnAddress])

sub rsp, 40h

mov [rsp + 28h], r12
.cfi_rel_offset r12, -18h
mov [rsp + 30h], r13
.cfi_rel_offset r13, -10h

mov r12, rdi // r12: entryObject
mov r13, rsi // r13: callInfo
Expand Down Expand Up @@ -267,7 +269,9 @@ NESTED_ENTRY _ZN2Js23AsmJsExternalEntryPointEPNS_16RecyclableObjectENS_8CallInfo
mov rsp, r13 // restore stack pointer
Epilogue:
mov r12, [rsp + 28h]
.cfi_restore r12
mov r13, [rsp + 30h]
.cfi_restore r13

lea rsp, [rbp]
pop_nonvol_reg rbp
Expand Down
1 change: 0 additions & 1 deletion lib/Runtime/Library/EngineInterfaceObjectBuiltIns.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ GlobalBuiltIn(JavascriptObject, EntryGetOwnPropertyNames)
GlobalBuiltIn(JavascriptObject, EntryHasOwnProperty)
GlobalBuiltIn(JavascriptObject, EntryKeys)

GlobalBuiltIn(JavascriptArray, EntryForEach)
GlobalBuiltIn(JavascriptArray, EntryPush)
GlobalBuiltIn(JavascriptArray, EntryJoin)
GlobalBuiltIn(JavascriptArray, EntryMap)
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Library/JavascriptArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8998,6 +8998,7 @@ using namespace Js;
return scriptContext->GetLibrary()->GetFalse();
}

// There is a Javascript built-in for forEach
Var JavascriptArray::EntryForEach(RecyclableObject* function, CallInfo callInfo, ...)
{
PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
Expand Down
4 changes: 1 addition & 3 deletions lib/Runtime/Library/JavascriptLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1770,9 +1770,6 @@ namespace Js

/* No inlining Array_Every */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::every, &JavascriptArray::EntryInfo::Every, 1);

/* No inlining Array_ForEach */
library->AddMember(arrayPrototype, PropertyIds::forEach, library->EnsureArrayPrototypeForEachFunction());

builtinFuncs[BuiltinFunction::JavascriptArray_LastIndexOf] = library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::lastIndexOf, &JavascriptArray::EntryInfo::LastIndexOf, 1);
/* No inlining Array_Map */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::map, &JavascriptArray::EntryInfo::Map, 1);
/* No inlining Array_Reduce */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::reduce, &JavascriptArray::EntryInfo::Reduce, 1);
Expand Down Expand Up @@ -1804,6 +1801,7 @@ namespace Js
/* No inlining Array_SymbolIterator */ library->AddMember(arrayPrototype, PropertyIds::_symbolIterator, values);

/* No inlining Array_Filter */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::filter, &JavascriptArray::EntryInfo::Filter, 1);
/* No inlining Array_ForEach */ library->AddMember(arrayPrototype, PropertyIds::forEach, library->EnsureArrayPrototypeForEachFunction());
}

if (scriptContext->GetConfig()->IsES6UnscopablesEnabled())
Expand Down
97 changes: 61 additions & 36 deletions lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
ArrayFilter: { className: "Array", methodName: "filter", argumentsCount: 1, forceInline: true /*optional*/ },
ArrayFlat: { className: "Array", methodName: "flat", argumentsCount: 0, forceInline: true /*optional*/ },
ArrayFlatMap: { className: "Array", methodName: "flatMap", argumentsCount: 1, forceInline: true /*optional*/ },
ArrayForEach: { className: "Array", methodName: "forEach", argumentsCount: 1, forceInline: true /*optional*/ },
};

var setPrototype = platform.builtInSetPrototype;
Expand Down Expand Up @@ -185,23 +186,27 @@
return -1;
});

platform.registerFunction(FunctionsEnum.ArrayFilter, function (callbackfn, thisArg) {
// ECMAScript 2017 #sec-array.prototype.filter
platform.registerChakraLibraryFunction("CheckArrayAndGetLen", function (obj, builtInFunc) {
"use strict";

if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.filter");
if (__chakraLibrary.isArray(obj)) {
return { o: obj, len: obj.length }
}

let o;
let len
if (__chakraLibrary.isArray(this)) {
o = this;
len = o.length;
} else {
o = __chakraLibrary.Object(this);
len = __chakraLibrary.GetLength(o);
else {
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined(builtInFunc);
}
return { o: __chakraLibrary.Object(obj), len: __chakraLibrary.GetLength(obj) }
}
});

platform.registerFunction(FunctionsEnum.ArrayFilter, function (callbackfn, thisArg) {
// ECMAScript 2017 #sec-array.prototype.filter
"use strict";

let objInfo = __chakraLibrary.CheckArrayAndGetLen(this, "Array.prototype.filter");
let o = objInfo.o;
let len = objInfo.len;

if (typeof callbackfn !== "function") {
__chakraLibrary.raiseFunctionArgument_NeedFunction("Array.prototype.filter");
Expand Down Expand Up @@ -358,18 +363,9 @@
"use strict";
//1. Let O be ? ToObject(this value).
//2. Let sourceLen be ? ToLength(? Get(O, "length")).
let o, sourceLen;

if (__chakraLibrary.isArray(this)) {
o = this;
sourceLen = o.length;
} else {
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.flat");
}
o = __chakraLibrary.Object(this);
sourceLen = __chakraLibrary.GetLength(o);
}
let objInfo = __chakraLibrary.CheckArrayAndGetLen(this, "Array.prototype.flat");
let o = objInfo.o;
let sourceLen = objInfo.len;
//3. Let depthNum be 1.
//4. If depth is not undefined, then
//5. Set depthNum to ? ToInteger(depth).
Expand All @@ -386,17 +382,11 @@
"use strict";
//1. Let O be ? ToObject(this value).
//2. Let sourceLen be ? ToLength(? Get(O, "length")).
let o, sourceLen;
if (__chakraLibrary.isArray(this)) {
o = this;
sourceLen = o.length;
} else {
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.flatMap");
}
o = __chakraLibrary.Object(this);
sourceLen = __chakraLibrary.GetLength(o);
}

let objInfo = __chakraLibrary.CheckArrayAndGetLen(this, "Array.prototype.flatMap");
let o = objInfo.o;
let sourceLen = objInfo.len;

//3. If IsCallable(mapperFunction) is false throw a TypeError exception
if (typeof mapperFunction !== "function") {
__chakraLibrary.raiseFunctionArgument_NeedFunction("Array.prototype.flatMap");
Expand All @@ -415,4 +405,39 @@
return A;
});

platform.registerFunction(FunctionsEnum.ArrayForEach, function (callbackfn, thisArg) {
// ECMAScript 2017 #sec-array.prototype.foreach
"use strict";

let objInfo = __chakraLibrary.CheckArrayAndGetLen(this, "Array.prototype.forEach");
let o = objInfo.o;
let len = objInfo.len;

if (typeof callbackfn !== "function") {
__chakraLibrary.raiseFunctionArgument_NeedFunction("Array.prototype.forEach");
}

let k = 0;

if (thisArg === undefined) {
while (k < len) {
if (k in o) {
let kValue = o[k];
callbackfn(kValue, k, o);
}
k++;
}
} else {
let boundCallback = __chakraLibrary.callInstanceFunc(__chakraLibrary.functionBind, callbackfn, thisArg);
while (k < len) {
if (k in o) {
let kValue = o[k];
boundCallback(kValue, k, o);
}
k++;
}
}

return undefined;
});
});
Loading

0 comments on commit 9fdbe23

Please sign in to comment.