mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 08:35:07 +08:00
Handle optional string-search needles with positions
This commit is contained in:
@@ -274,7 +274,8 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
if ((entry.method === "indexOf" || entry.method === "includes" ||
|
||||
entry.method === "startsWith" || entry.method === "endsWith") && call.arguments.length === 2) {
|
||||
const needle = lowerer.lowerExpr(call.arguments[0]!);
|
||||
if (needle.type.kind !== "string" && needle.type.kind !== "dyn") {
|
||||
const optionalNeedle = needle.type.kind === "union" && lowerer.runtimeOptionalWidening(needle.type, STRING) !== null;
|
||||
if (needle.type.kind !== "string" && needle.type.kind !== "dyn" && !optionalNeedle) {
|
||||
lowerer.noLowering(`.${entry.method} with '${lowerer.fmt(needle.type)}' search values`, call);
|
||||
}
|
||||
const defaultPosition: IrExpr = entry.method === "endsWith"
|
||||
@@ -289,8 +290,8 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
if (!helper) {
|
||||
helper = `%str.positions.${lowerer.widthHelpers.size}`;
|
||||
const params = [receiver, needle, position].map((arg, index) => ({ localId: `arg.${index}`, name: `arg${index}`, type: arg.type }));
|
||||
const dynamicNeedle = needle.type.kind === "dyn";
|
||||
const search: IrExpr = dynamicNeedle ? varRef("search.0", STRING, loc) : varRef("arg.1", STRING, loc);
|
||||
const coerceNeedle = needle.type.kind !== "string";
|
||||
const search: IrExpr = coerceNeedle ? varRef("search.0", STRING, loc) : varRef("arg.1", STRING, loc);
|
||||
const result: IrExpr = {
|
||||
kind: "strIntrinsic", method: entry.method, receiver: varRef("arg.0", STRING, loc),
|
||||
args: [
|
||||
@@ -301,11 +302,13 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
};
|
||||
const locals = params.map(param => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
|
||||
const body: IrStmt[] = [];
|
||||
if (dynamicNeedle) {
|
||||
if (coerceNeedle) {
|
||||
const value = varRef("arg.1", needle.type, loc);
|
||||
const init: IrExpr = needle.type.kind === "dyn"
|
||||
? { kind: "libCall", fn: "dyn.toStringCoerce", args: [value], type: STRING, loc }
|
||||
: lowerer.ensureString(value, call.arguments[0]!);
|
||||
locals.push({ id: "search.0", name: "search", type: STRING, mutable: false });
|
||||
body.push({ kind: "varDecl", localId: "search.0", init: {
|
||||
kind: "libCall", fn: "dyn.toStringCoerce", args: [varRef("arg.1", needle.type, loc)], type: STRING, loc,
|
||||
}, loc });
|
||||
body.push({ kind: "varDecl", localId: "search.0", init, loc });
|
||||
}
|
||||
body.push({ kind: "return", value: result, loc });
|
||||
lowerer.widthHelpers.set(key, helper);
|
||||
|
||||
@@ -6943,6 +6943,12 @@
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3029-string-search-union-needle.js": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3029-string-search-union-needle.js"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/303-break-continue.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/303-break-continue.ts"
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/** @param {string | undefined} needle */
|
||||
function probe(needle) {
|
||||
const value = "ababa";
|
||||
console.log(
|
||||
value.indexOf(needle),
|
||||
value.indexOf(needle, 1),
|
||||
value.includes(needle),
|
||||
value.includes(needle, 1),
|
||||
value.startsWith(needle),
|
||||
value.startsWith(needle, 1),
|
||||
value.endsWith(needle),
|
||||
value.endsWith(needle, 2),
|
||||
);
|
||||
}
|
||||
|
||||
probe("ba");
|
||||
probe(undefined);
|
||||
Reference in New Issue
Block a user