mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 00:25:34 +08:00
Lower static String prototype call forms (#448)
This commit is contained in:
@@ -237,7 +237,9 @@ export function lowerRegexMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
* Complete position defaults and conversions here for both backends. */
|
||||
export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
access: ts.PropertyAccessExpression,
|
||||
dynReceiver?: () => IrExpr,): IrExpr | null {
|
||||
dynReceiver?: () => IrExpr,
|
||||
argumentNodes: readonly ts.Expression[] = call.arguments,
|
||||
): IrExpr | null {
|
||||
if (lowerer.chainBlocked(access, call)) return null;
|
||||
if (dynReceiver === undefined && access.name.text === "localeCompare") return lowerLocaleCompareCall(lowerer, call, access);
|
||||
const entry = own(STR_METHODS, access.name.text);
|
||||
@@ -261,9 +263,9 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
}
|
||||
// The lib declares optional parameters beyond some lowered forms; fence
|
||||
// those arities instead of passing arguments the runtime doesn't take.
|
||||
if (call.arguments.length < entry.minArgs || call.arguments.length > entry.maxArgs) {
|
||||
if (argumentNodes.length < entry.minArgs || argumentNodes.length > entry.maxArgs) {
|
||||
lowerer.noLowering(
|
||||
`.${access.name.text} with ${call.arguments.length} argument${call.arguments.length === 1 ? "" : "s"} on strings`,
|
||||
`.${access.name.text} with ${argumentNodes.length} argument${argumentNodes.length === 1 ? "" : "s"} on strings`,
|
||||
call,
|
||||
);
|
||||
}
|
||||
@@ -273,12 +275,12 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
const loc = locOf(call);
|
||||
const searchMethod = entry.method === "indexOf" || entry.method === "includes" ||
|
||||
entry.method === "startsWith" || entry.method === "endsWith";
|
||||
if (searchMethod && call.arguments.length < 2) {
|
||||
const needle = lowerStringSearchArgument(lowerer, call.arguments[0], loc);
|
||||
if (searchMethod && argumentNodes.length < 2) {
|
||||
const needle = lowerStringSearchArgument(lowerer, argumentNodes[0], loc);
|
||||
return { kind: "strIntrinsic", method: entry.method, receiver, args: [needle], type: entry.result, loc };
|
||||
}
|
||||
if (searchMethod && call.arguments.length === 2) {
|
||||
const needleNode = call.arguments[0]!;
|
||||
if (searchMethod && argumentNodes.length === 2) {
|
||||
const needleNode = argumentNodes[0]!;
|
||||
const undefinedArg = lowerStaticallyUndefinedArgument(lowerer, needleNode);
|
||||
let needle = undefinedArg
|
||||
? defaultAfterUndefined(undefinedArg, strLit("undefined", loc))
|
||||
@@ -294,7 +296,7 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
const defaultPosition: IrExpr = entry.method === "endsWith"
|
||||
? { kind: "bin", op: "/", left: numLit(1, loc), right: numLit(0, loc), type: F64, loc }
|
||||
: numLit(0, loc);
|
||||
const position = lowerPositionArgument(lowerer, call.arguments[1], defaultPosition);
|
||||
const position = lowerPositionArgument(lowerer, argumentNodes[1], defaultPosition);
|
||||
if (needle.type.kind === "string" && (position.type.kind === "f64" || position.type.kind === "jsval")) {
|
||||
return { kind: "strIntrinsic", method: entry.method, receiver, args: [needle, position], type: entry.result, loc };
|
||||
}
|
||||
@@ -309,7 +311,7 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
kind: "strIntrinsic", method: entry.method, receiver: varRef("arg.0", STRING, loc),
|
||||
args: [
|
||||
search,
|
||||
positionNumber(lowerer, varRef("arg.2", position.type, loc), defaultPosition, call.arguments[1]!, "string position"),
|
||||
positionNumber(lowerer, varRef("arg.2", position.type, loc), defaultPosition, argumentNodes[1]!, "string position"),
|
||||
],
|
||||
type: entry.result, loc,
|
||||
};
|
||||
@@ -337,7 +339,7 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
if (entry.method === "slice" || entry.method === "substring") {
|
||||
defaults.push({ kind: "bin", op: "/", left: numLit(1, loc), right: numLit(0, loc), type: F64, loc });
|
||||
}
|
||||
const args = defaults.map((value, index) => lowerPositionArgument(lowerer, call.arguments[index], value));
|
||||
const args = defaults.map((value, index) => lowerPositionArgument(lowerer, argumentNodes[index], value));
|
||||
const subject = entry.method === "repeat" ? "string repeat count" : "string position";
|
||||
// Keep ordinary numeric calls on the direct intrinsic path, including the
|
||||
// existing boundary validation for island values in numeric slots.
|
||||
@@ -354,7 +356,7 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
const params = [receiver, ...args].map((arg, index) => ({ localId: `arg.${index}`, name: `arg${index}`, type: arg.type }));
|
||||
const result: IrExpr = {
|
||||
kind: "strIntrinsic", method: entry.method, receiver: varRef("arg.0", STRING, loc),
|
||||
args: args.map((arg, index) => positionNumber(lowerer, varRef(`arg.${index + 1}`, arg.type, loc), defaults[index]!, call.arguments[index] ?? call, subject)),
|
||||
args: args.map((arg, index) => positionNumber(lowerer, varRef(`arg.${index + 1}`, arg.type, loc), defaults[index]!, argumentNodes[index] ?? call, subject)),
|
||||
type: entry.result, loc,
|
||||
};
|
||||
lowerer.widthHelpers.set(key, helper);
|
||||
@@ -367,15 +369,15 @@ export function lowerStringMethodCall(lowerer: Lowerer, call: ts.CallExpression,
|
||||
return { kind: "call", callee: helper, args: [receiver, ...args], type: entry.result, loc };
|
||||
}
|
||||
const args = entry.method === "split"
|
||||
? [lowerer.lowerExpr(call.arguments[0]!), lowerSplitLimitArg(lowerer, call.arguments[1], locOf(call))]
|
||||
: call.arguments.map((a) => lowerer.lowerExpr(a));
|
||||
? [lowerer.lowerExpr(argumentNodes[0]!), lowerSplitLimitArg(lowerer, argumentNodes[1], locOf(call))]
|
||||
: argumentNodes.map((a) => lowerer.lowerExpr(a));
|
||||
// split's separator must BE a string here (a regex argument was
|
||||
// claimed by lowerRegexMethodCall before this path) — the lib's
|
||||
// `string | RegExp` union has no lowering as a VALUE.
|
||||
if (entry.method === "split" && args[0]!.type.kind !== "string") {
|
||||
lowerer.unsupported(
|
||||
"SC1090",
|
||||
call.arguments[0]!,
|
||||
argumentNodes[0]!,
|
||||
`'.split()' on a '${lowerer.fmt(args[0]!.type)}' separator (pass a string, or a regex literal)`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { isJsSourceFile, isNodeEsmFile, locOf } from "../program.js";
|
||||
import { genResultRecord, isGenericCallableMemberType, typeKey } from "../type-mapper.js";
|
||||
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
|
||||
import { enforceLibBoundary } from "./lib-boundary.js";
|
||||
import { NARROW_FIRST, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
||||
import { NARROW_FIRST, STR_METHODS, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
||||
import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
||||
import type { ScrDiagnostic } from "../../diagnostics/diagnostic.js";
|
||||
import { mixinFnShapeOf } from "./lower-mixins.js";
|
||||
@@ -4659,6 +4659,7 @@ export function lowerCall(lowerer: Lowerer, expr: ts.CallExpression): IrExpr {
|
||||
// TestContext surface (t.test/t.skip/t.diagnostic), t.assert.*.
|
||||
lowerer.lowerTestMethodCall(expr, expr.expression) ??
|
||||
lowerer.lowerTimeoutMethodCall(expr, expr.expression) ??
|
||||
lowerStringPrototypeCall(lowerer, expr, expr.expression) ??
|
||||
lowerStringMethodCallWithOptionalArgs(lowerer, expr, expr.expression) ??
|
||||
// Typed-array/Buffer receivers and the Buffer statics — before the
|
||||
// island path (bytes never cross the boundary).
|
||||
@@ -5032,8 +5033,10 @@ function lowerStringMethodCallWithOptionalArgs(
|
||||
lowerer: Lowerer,
|
||||
call: ts.CallExpression,
|
||||
access: ts.PropertyAccessExpression,
|
||||
receiver?: () => IrExpr,
|
||||
argumentNodes: readonly ts.Expression[] = call.arguments,
|
||||
): IrExpr | null {
|
||||
const lowered = lowerer.lowerStringMethodCall(call, access);
|
||||
const lowered = lowerStringMethodCall(lowerer, call, access, receiver, argumentNodes);
|
||||
if (lowered?.kind !== "strIntrinsic") return lowered;
|
||||
const args = [...lowered.args];
|
||||
let changed = false;
|
||||
@@ -5061,12 +5064,60 @@ function lowerStringMethodCallWithOptionalArgs(
|
||||
args[0]?.type.kind === "union" &&
|
||||
lowerer.runtimeOptionalWidening(args[0].type, STRING) !== null
|
||||
) {
|
||||
args[0] = lowerer.ensureString(args[0], call.arguments[0]!);
|
||||
args[0] = lowerer.ensureString(args[0], argumentNodes[0]!);
|
||||
changed = true;
|
||||
}
|
||||
return changed ? { ...lowered, args } : lowered;
|
||||
}
|
||||
|
||||
function lowerStringPrototypeCall(
|
||||
lowerer: Lowerer,
|
||||
call: ts.CallExpression,
|
||||
access: ts.PropertyAccessExpression,
|
||||
): IrExpr | null {
|
||||
if (access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression)) return null;
|
||||
const methodAccess = access.expression;
|
||||
const prototypeAccess = methodAccess.expression;
|
||||
if (!ts.isPropertyAccessExpression(prototypeAccess) || prototypeAccess.name.text !== "prototype" ||
|
||||
!ts.isIdentifier(prototypeAccess.expression) || prototypeAccess.expression.text !== "String" ||
|
||||
!Object.hasOwn(STR_METHODS, methodAccess.name.text) || !lowerer.isStdlibMember(methodAccess)) return null;
|
||||
if (call.arguments.some(ts.isSpreadElement)) return null;
|
||||
const entry = STR_METHODS[methodAccess.name.text]!;
|
||||
const method = methodAccess.name.text === "trimStart" ? "trimLeft" :
|
||||
methodAccess.name.text === "trimEnd" ? "trimRight" : methodAccess.name.text;
|
||||
const loc = locOf(call);
|
||||
const nullishError = nodeThrowExpr(1, "", `String.prototype.${method} called on null or undefined`, entry.result, loc);
|
||||
const receiverNode = call.arguments[0];
|
||||
if (!receiverNode) return nullishError;
|
||||
const receiverValue = lowerer.lowerExpr(receiverNode);
|
||||
const receiverType = receiverValue.type;
|
||||
const nullish = isUnitType(receiverType) || receiverType.kind === "void" ||
|
||||
(receiverType.kind === "union" && (lowerer.unions.get(receiverType.unionId)?.arms.every((arm) =>
|
||||
isUnitType(arm) || arm.kind === "void") ?? false));
|
||||
if (nullish) {
|
||||
const values = [receiverValue, ...call.arguments.slice(1).map((arg) => lowerer.lowerExpr(arg))];
|
||||
return {
|
||||
kind: "seqExpr",
|
||||
stmts: values.filter((value) => !isSafeToDiscard(value)).map((value) => ({ kind: "exprStmt", expr: value, loc: value.loc })),
|
||||
result: nullishError,
|
||||
type: entry.result,
|
||||
loc,
|
||||
};
|
||||
}
|
||||
const scalar = receiverType.kind === "string" || receiverType.kind === "f64" ||
|
||||
receiverType.kind === "bool" || receiverType.kind === "bigint" ||
|
||||
(receiverType.kind === "union" && (lowerer.unions.get(receiverType.unionId)?.arms.every((arm) =>
|
||||
arm.kind === "string" || arm.kind === "f64" || arm.kind === "bool" || arm.kind === "bigint") ?? false));
|
||||
// Object conversion may run user code, so no later method arguments can remain to evaluate.
|
||||
const objectWithoutMethodArgs = entry.maxArgs === 0 && call.arguments.length === 1 &&
|
||||
(receiverType.kind === "record" || receiverType.kind === "array" || receiverType.kind === "object");
|
||||
if (!scalar && !objectWithoutMethodArgs) {
|
||||
return lowerer.noLowering(`String.prototype.${methodAccess.name.text}.call with ${lowerer.fmt(receiverType)} receivers`, call);
|
||||
}
|
||||
const receiver = lowerer.ensureString(receiverValue, receiverNode);
|
||||
return lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => receiver, call.arguments.slice(1));
|
||||
}
|
||||
|
||||
function lowerScalarUnionNumber(lowerer: Lowerer, arg: IrExpr, node: ts.Expression, loc: SrcLoc): IrExpr | null {
|
||||
if (arg.type.kind !== "union" || !lowerer.unions.get(arg.type.unionId)?.arms.every(
|
||||
(arm) => arm.kind === "f64" || arm.kind === "string" || arm.kind === "bool" || isUnitType(arm)
|
||||
|
||||
@@ -7021,6 +7021,12 @@
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/3040-string-prototype-call.js": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/3040-string-prototype-call.js"
|
||||
],
|
||||
"diags": []
|
||||
},
|
||||
"<repo>/tests/corpus/305-truthiness.ts": {
|
||||
"order": [
|
||||
"<repo>/tests/corpus/305-truthiness.ts"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
console.log(String.prototype.trim.call(" \u00a0 x \n"), String.prototype.trim.call(false), String.prototype.trim.call(-0));
|
||||
console.log(String.prototype.trimStart.call(12), String.prototype.trimEnd.call(true));
|
||||
console.log(String.prototype.trimLeft.call(" x"), String.prototype.trimRight.call("x "));
|
||||
console.log(String.prototype.charAt.call(12345, 2), String.prototype.charCodeAt.call("AB", 1));
|
||||
console.log(String.prototype.indexOf.call(12345, "3"), String.prototype.includes.call(12345, 34));
|
||||
console.log(String.prototype.startsWith.call("abc", "b", 1), String.prototype.endsWith.call("abc", "b", 2));
|
||||
console.log(String.prototype.slice.call(true, 1), String.prototype.substring.call("abcdef", "2", "4"));
|
||||
console.log(String.prototype.repeat.call(12, "2"), String.prototype.padStart.call(42, 4, "0"), String.prototype.padEnd.call(42, 4, "0"));
|
||||
console.log(String.prototype.split.call("a,b", ",").join("|"), String.prototype.toLowerCase.call("ABC"), String.prototype.toUpperCase.call("abc"));
|
||||
console.log(String.prototype.trim.call({}), String.prototype.trim.call([1, 2]), String.prototype.trim.call(new Error("test")));
|
||||
|
||||
const scalar = Math.floor(1.9) === 1 ? 42 : " abc ";
|
||||
console.log(String.prototype.trim.call(scalar));
|
||||
|
||||
let trace = "";
|
||||
function receiver() { trace += "r"; return " ab "; }
|
||||
function search() { trace += "s"; return "a"; }
|
||||
function position() { trace += "p"; return "2"; }
|
||||
console.log(String.prototype.indexOf.call(receiver(), search(), position()), trace);
|
||||
|
||||
let nullishTrace = "";
|
||||
function nullReceiver() { nullishTrace += "r"; return null; }
|
||||
function searched() { nullishTrace += "s"; return "x"; }
|
||||
try {
|
||||
String.prototype.indexOf.call(nullReceiver(), searched());
|
||||
} catch (error) {
|
||||
console.log(nullishTrace, error.name);
|
||||
}
|
||||
try {
|
||||
String.prototype.trim.call(undefined);
|
||||
} catch (error) {
|
||||
console.log(error.name);
|
||||
}
|
||||
try {
|
||||
String.prototype.split.call();
|
||||
} catch (error) {
|
||||
console.log(error.name);
|
||||
}
|
||||
|
||||
let extraTrace = "";
|
||||
function extra() { extraTrace += "e"; throw new Error("argument"); }
|
||||
try {
|
||||
String.prototype.trim.call(null, extra());
|
||||
} catch (error) {
|
||||
console.log(extraTrace, error.message);
|
||||
}
|
||||
@@ -83,6 +83,20 @@
|
||||
"test/built-ins/String/prototype/startsWith/searchstring-found-with-position.js",
|
||||
"test/built-ins/String/prototype/startsWith/searchstring-not-found-with-position.js",
|
||||
"test/built-ins/String/prototype/substring/S15.5.4.15_A1_T4.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-3.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-4.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-5.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-7.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-1.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-10.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-15.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-16.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-18.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-19.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-27.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-47.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-50.js",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-6.js",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T1.js",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T2.js",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T3.js",
|
||||
@@ -186,6 +200,20 @@
|
||||
"test/built-ins/String/prototype/startsWith/searchstring-found-with-position.js": "b7bb997f562d672d919e0f4e9c994ff42a7f1b5bf2858f33c0bdc3b689ecde4f",
|
||||
"test/built-ins/String/prototype/startsWith/searchstring-not-found-with-position.js": "333fe4703bef1a9d7e1819153216aeaefa48a97eb546bc680dbeb2cf0cd77af6",
|
||||
"test/built-ins/String/prototype/substring/S15.5.4.15_A1_T4.js": "9bf9c2c32206d9b3c6af0ca156e8b87d7d3978153a803ffaaedaac7e9a04e5bb",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-3.js": "a4b02a4343ceaa0252801ddc4f14e4bea6d0865fa091e35d0208760cbfe75b3b",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-4.js": "74abb7d23585d6a8be9e8e4d76a7671208896d39fd6834782daa6fd77d1ac85f",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-5.js": "635953ee4b01a953143839adf17defb653a7eddab6d58b6aa125e2206dfeae52",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-1-7.js": "2733b093914828ae18279e52c76cf8dacd44a45f668b048b9bcdfa0c862f10a0",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-1.js": "f2434055c69276e47fa9dcd3ad011a9d94d184037dfda4eed672e69078a6bc80",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-10.js": "690f384f84a3be7feb199e634c8f7d16c95e0b5eb040fd5b2a5fb2b9c67076a8",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-15.js": "3d6c790488a9ce532695663818146f32cc311e49f972244f644ca4e9ee01e258",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-16.js": "fccc1fb180d4800816370483e85e1be542f095ce5acfa482ca2cf4e81322d6ac",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-18.js": "9119005f9642477fdcb512da167b0af7f7c0111eddae69d2e50660f65490d93d",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-19.js": "dca675e1f8269bc9f3b4e03b9522d1d6c7c93dd5bff1187d98b5a51ae3fdb214",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-27.js": "810993546eab06216c6d03a9590bf747281e5ffaaf739bfe238fee581340967c",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-47.js": "3e1a745af465177a96a29601e56299afc044060dbc2ac3061a59032be451cfde",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-50.js": "38b84997faa99e422408917eeac7f3575bd6064b429ea390a9d041fd77fce532",
|
||||
"test/built-ins/String/prototype/trim/15.5.4.20-2-6.js": "3d5857f24117f65f07a70edd0d254dfa07f593c76effed94500847ccf8564c06",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T1.js": "12928eb319dcf0cc785e399580effb0b7495709296dce9c0a58e8408616a959f",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T2.js": "aee914241b607f56a98de04492f2d580e7bc69cca232af679d0c02b7025cc06b",
|
||||
"test/language/expressions/addition/S11.6.1_A4_T3.js": "987b1c3cf66b6bbb2f6d8aaf6d1435cb1238b19132fa861a91aa2c35085d229d",
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-1-3
|
||||
description: String.prototype.trim works for primitive type boolean
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(true), "true", 'String.prototype.trim.call(true)');
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-1-4
|
||||
description: String.prototype.trim works for primitive type number
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(0), "0", 'String.prototype.trim.call(0)');
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-1-5
|
||||
description: String.prototype.trim works for an Object
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call({}), "[object Object]", 'String.prototype.trim.call({})');
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-1-7
|
||||
description: String.prototype.trim works for a primitive string
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call("abc"), "abc", 'String.prototype.trim.call("abc")');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-1
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a boolean whose value
|
||||
is false
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(false), "false", 'String.prototype.trim.call(false)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-10
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to a string (value is +Infinity)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(+Infinity), "Infinity", 'String.prototype.trim.call(+Infinity)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-15
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to a string (value is 1e+20)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(1e+20), "100000000000000000000", 'String.prototype.trim.call(1e+20)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-16
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to string (value is 1e+21)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(1e+21), "1e+21", 'String.prototype.trim.call(1e+21)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-18
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to a string (value is 0.000001)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(0.000001), "0.000001", 'String.prototype.trim.call(0.000001)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-19
|
||||
description: >
|
||||
String.prototype.trim - argument argument 'this' is a number that
|
||||
converts to a string (value is 0.0000001)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(0.0000001), "1e-7", 'String.prototype.trim.call(0.0000001)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-27
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to a string (value is 123.1234567)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(123.1234567), "123.1234567", 'String.prototype.trim.call(123.1234567)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-47
|
||||
description: >
|
||||
String.prototype.trim - 'this' is a object Object that converts to
|
||||
a string
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call({}), "[object Object]", 'String.prototype.trim.call({})');
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-50
|
||||
description: >
|
||||
String.prototype.trim - 'this' is a Error Object that converts to
|
||||
a string
|
||||
---*/
|
||||
|
||||
var errObj = new Error("test");
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(errObj), "Error: test", 'String.prototype.trim.call(errObj)');
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2012 Ecma International. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
es5id: 15.5.4.20-2-6
|
||||
description: >
|
||||
String.prototype.trim - argument 'this' is a number that converts
|
||||
to a string (value is -0)
|
||||
---*/
|
||||
|
||||
assert.sameValue(String.prototype.trim.call(-0), "0", 'String.prototype.trim.call(-0)');
|
||||
Reference in New Issue
Block a user