diff --git a/scripts/build/shims/array-find-last-index.js b/scripts/build/shims/array-find-last-index.js new file mode 100644 index 000000000..ceb4b9905 --- /dev/null +++ b/scripts/build/shims/array-find-last-index.js @@ -0,0 +1,20 @@ +const arrayFindLastIndex = (isOptionalObject, array, callback) => { + if (isOptionalObject && (array === undefined || array === null)) { + return; + } + + if (array.findLastIndex) { + return array.findLastIndex(callback); + } + + for (let index = array.length - 1; index >= 0; index--) { + const element = array[index]; + if (callback(element, index, array)) { + return index; + } + } + + return -1; +}; + +export default arrayFindLastIndex; diff --git a/scripts/build/transform/transforms/index.js b/scripts/build/transform/transforms/index.js index b0a25317a..cb2535007 100644 --- a/scripts/build/transform/transforms/index.js +++ b/scripts/build/transform/transforms/index.js @@ -1,11 +1,13 @@ import transformArrayFindLast from "./transform-array-find-last.js"; +import transformArrayFindLastIndex from "./transform-array-find-last-index.js"; import transformObjectHasOwnCall from "./transform-object-has-own.js"; import transformRelativeIndexing from "./transform-relative-indexing.js"; import transformStringReplaceAll from "./transform-string-replace-all.js"; export default [ + transformArrayFindLast, + transformArrayFindLastIndex, transformObjectHasOwnCall, transformRelativeIndexing, transformStringReplaceAll, - transformArrayFindLast, ]; diff --git a/scripts/build/transform/transforms/transform-array-find-last-index.js b/scripts/build/transform/transforms/transform-array-find-last-index.js new file mode 100644 index 000000000..68598bb53 --- /dev/null +++ b/scripts/build/transform/transforms/transform-array-find-last-index.js @@ -0,0 +1,13 @@ +import createMethodCallTransform from "./create-method-call-transform.js"; + +const transformArrayFindLastIndex = createMethodCallTransform({ + methodName: "findLastIndex", + argumentsLength: 1, + functionName: "__arrayFindLastIndex", + functionImplementationUrl: new URL( + "../../shims/array-find-last-index.js", + import.meta.url, + ), +}); + +export default transformArrayFindLastIndex; diff --git a/src/main/range-util.js b/src/main/range-util.js index 8cc02b443..2fe5f7ad4 100644 --- a/src/main/range-util.js +++ b/src/main/range-util.js @@ -24,16 +24,15 @@ function findCommonAncestor(startNodeAndParents, endNodeAndParents) { } function dropRootParents(parents) { - let lastParentIndex = parents.length - 1; - while (true) { - const parent = parents[lastParentIndex]; - if (parent?.type === "Program" || parent?.type === "File") { - lastParentIndex--; - } else { - break; - } + const index = parents.findLastIndex( + (node) => node.type !== "Program" && node.type !== "File", + ); + + if (index === -1) { + return parents; } - return parents.slice(0, lastParentIndex + 1); + + return parents.slice(0, index + 1); } function findSiblingAncestors( diff --git a/tests/unit/syntax-transform.js b/tests/unit/syntax-transform.js index 8421e46a6..6eff893cb 100644 --- a/tests/unit/syntax-transform.js +++ b/tests/unit/syntax-transform.js @@ -75,3 +75,21 @@ test("Array#findLast", () => { transform("foo.findLast(callback, thisArgument)"), ).toMatchInlineSnapshot(`"foo.findLast(callback, thisArgument)"`); }); + +test("Array#findLastIndex", () => { + expect(transform("foo.findLastIndex(callback)")).toMatchInlineSnapshot(` + "import __arrayFindLastIndex from "/array-find-last-index.js"; + + __arrayFindLastIndex( /* isOptionalObject */false, foo, callback);" + `); + expect(transform("foo?.findLastIndex(callback)")).toMatchInlineSnapshot(` + "import __arrayFindLastIndex from "/array-find-last-index.js"; + + __arrayFindLastIndex( /* isOptionalObject */true, foo, callback);" + `); + + // Don't support + expect( + transform("foo.findLastIndex(callback, thisArgument)"), + ).toMatchInlineSnapshot(`"foo.findLastIndex(callback, thisArgument)"`); +});