[builtins] Port String.prototype HTML functions to Torque

Consolidates all the work into a single TFS builtin (CreateHTML)
called by all these functions. Reduces the builtin size by
about half.

Change-Id: I92b2c7889f72db4c8c79d7ef0ce0e61036ab619e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1522727
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60248}
This commit is contained in:
peterwmwong 2019-03-14 08:26:28 -05:00 committed by Commit Bot
parent d68cdcae8f
commit 4b9b23521e
11 changed files with 182 additions and 214 deletions

View File

@ -938,6 +938,7 @@ torque_files = [
"src/builtins/object-fromentries.tq",
"src/builtins/iterator.tq",
"src/builtins/string-endswith.tq",
"src/builtins/string-html.tq",
"src/builtins/string-startswith.tq",
"src/builtins/typed-array.tq",
"src/builtins/typed-array-createtypedarray.tq",
@ -980,6 +981,7 @@ torque_namespaces = [
"iterator",
"object",
"string",
"string-html",
"test",
"typed-array",
"typed-array-createtypedarray",

View File

@ -1943,13 +1943,13 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
// Install the String.prototype methods.
SimpleInstallFunction(isolate_, prototype, "anchor",
Builtins::kStringPrototypeAnchor, 1, true);
Builtins::kStringPrototypeAnchor, 1, false);
SimpleInstallFunction(isolate_, prototype, "big",
Builtins::kStringPrototypeBig, 0, true);
Builtins::kStringPrototypeBig, 0, false);
SimpleInstallFunction(isolate_, prototype, "blink",
Builtins::kStringPrototypeBlink, 0, true);
Builtins::kStringPrototypeBlink, 0, false);
SimpleInstallFunction(isolate_, prototype, "bold",
Builtins::kStringPrototypeBold, 0, true);
Builtins::kStringPrototypeBold, 0, false);
SimpleInstallFunction(isolate_, prototype, "charAt",
Builtins::kStringPrototypeCharAt, 1, true);
SimpleInstallFunction(isolate_, prototype, "charCodeAt",
@ -1961,21 +1961,21 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(isolate_, prototype, "endsWith",
Builtins::kStringPrototypeEndsWith, 1, false);
SimpleInstallFunction(isolate_, prototype, "fontcolor",
Builtins::kStringPrototypeFontcolor, 1, true);
Builtins::kStringPrototypeFontcolor, 1, false);
SimpleInstallFunction(isolate_, prototype, "fontsize",
Builtins::kStringPrototypeFontsize, 1, true);
Builtins::kStringPrototypeFontsize, 1, false);
SimpleInstallFunction(isolate_, prototype, "fixed",
Builtins::kStringPrototypeFixed, 0, true);
Builtins::kStringPrototypeFixed, 0, false);
SimpleInstallFunction(isolate_, prototype, "includes",
Builtins::kStringPrototypeIncludes, 1, false);
SimpleInstallFunction(isolate_, prototype, "indexOf",
Builtins::kStringPrototypeIndexOf, 1, false);
SimpleInstallFunction(isolate_, prototype, "italics",
Builtins::kStringPrototypeItalics, 0, true);
Builtins::kStringPrototypeItalics, 0, false);
SimpleInstallFunction(isolate_, prototype, "lastIndexOf",
Builtins::kStringPrototypeLastIndexOf, 1, false);
SimpleInstallFunction(isolate_, prototype, "link",
Builtins::kStringPrototypeLink, 1, true);
Builtins::kStringPrototypeLink, 1, false);
#ifdef V8_INTL_SUPPORT
SimpleInstallFunction(isolate_, prototype, "localeCompare",
Builtins::kStringPrototypeLocaleCompare, 1, false);
@ -2005,19 +2005,19 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(isolate_, prototype, "slice",
Builtins::kStringPrototypeSlice, 2, false);
SimpleInstallFunction(isolate_, prototype, "small",
Builtins::kStringPrototypeSmall, 0, true);
Builtins::kStringPrototypeSmall, 0, false);
SimpleInstallFunction(isolate_, prototype, "split",
Builtins::kStringPrototypeSplit, 2, false);
SimpleInstallFunction(isolate_, prototype, "strike",
Builtins::kStringPrototypeStrike, 0, true);
Builtins::kStringPrototypeStrike, 0, false);
SimpleInstallFunction(isolate_, prototype, "sub",
Builtins::kStringPrototypeSub, 0, true);
Builtins::kStringPrototypeSub, 0, false);
SimpleInstallFunction(isolate_, prototype, "substr",
Builtins::kStringPrototypeSubstr, 2, false);
SimpleInstallFunction(isolate_, prototype, "substring",
Builtins::kStringPrototypeSubstring, 2, false);
SimpleInstallFunction(isolate_, prototype, "sup",
Builtins::kStringPrototypeSup, 0, true);
Builtins::kStringPrototypeSup, 0, false);
SimpleInstallFunction(isolate_, prototype, "startsWith",
Builtins::kStringPrototypeStartsWith, 1, false);
SimpleInstallFunction(isolate_, prototype, "toString",

View File

@ -821,6 +821,7 @@ extern macro ToSmiIndex(implicit context: Context)(Object): PositiveSmi
extern macro ToSmiLength(implicit context: Context)(Object): PositiveSmi
labels IfRangeError;
extern macro ToString_Inline(Context, Object): String;
extern macro ToThisString(implicit context: Context)(Object, String): String;
extern transitioning macro GetProperty(implicit context: Context)(
Object, Object): Object;
extern transitioning builtin SetProperty(implicit context: Context)(
@ -1092,6 +1093,13 @@ extern operator '.length' macro GetArgumentsLength(constexpr Arguments): intptr;
extern operator '[]' macro GetArgumentValue(
constexpr Arguments, intptr): Object;
extern builtin StringAdd_CheckNone(implicit context: Context)(
String, String): String;
operator '+' macro StringAdd(implicit context: Context)(
a: String, b: String): String {
return StringAdd_CheckNone(a, b);
}
extern macro TaggedIsSmi(Object): bool;
extern macro TaggedIsNotSmi(Object): bool;
extern macro TaggedIsPositiveSmi(Object): bool;

View File

@ -997,14 +997,6 @@ namespace internal {
CPP(StringFromCodePoint) \
/* ES6 #sec-string.fromcharcode */ \
TFJ(StringFromCharCode, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.anchor */ \
TFJ(StringPrototypeAnchor, 1, kReceiver, kValue) \
/* ES6 #sec-string.prototype.big */ \
TFJ(StringPrototypeBig, 0, kReceiver) \
/* ES6 #sec-string.prototype.blink */ \
TFJ(StringPrototypeBlink, 0, kReceiver) \
/* ES6 #sec-string.prototype.bold */ \
TFJ(StringPrototypeBold, 0, kReceiver) \
/* ES6 #sec-string.prototype.charat */ \
TFJ(StringPrototypeCharAt, 1, kReceiver, kPosition) \
/* ES6 #sec-string.prototype.charcodeat */ \
@ -1013,23 +1005,13 @@ namespace internal {
TFJ(StringPrototypeCodePointAt, 1, kReceiver, kPosition) \
/* ES6 #sec-string.prototype.concat */ \
TFJ(StringPrototypeConcat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.fontcolor */ \
TFJ(StringPrototypeFontcolor, 1, kReceiver, kValue) \
/* ES6 #sec-string.prototype.fontsize */ \
TFJ(StringPrototypeFontsize, 1, kReceiver, kValue) \
/* ES6 #sec-string.prototype.fixed */ \
TFJ(StringPrototypeFixed, 0, kReceiver) \
/* ES6 #sec-string.prototype.includes */ \
TFJ(StringPrototypeIncludes, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.indexof */ \
TFJ(StringPrototypeIndexOf, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.italics */ \
TFJ(StringPrototypeItalics, 0, kReceiver) \
/* ES6 #sec-string.prototype.lastindexof */ \
CPP(StringPrototypeLastIndexOf) \
/* ES6 #sec-string.prototype.link */ \
TFJ(StringPrototypeLink, 1, kReceiver, kValue) \
/* ES6 #sec-string.prototype.match */ \
TFJ(StringPrototypeMatch, 1, kReceiver, kRegexp) \
/* ES #sec-string.prototype.matchAll */ \
@ -1049,21 +1031,13 @@ namespace internal {
TFJ(StringPrototypeSearch, 1, kReceiver, kRegexp) \
/* ES6 #sec-string.prototype.slice */ \
TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.small */ \
TFJ(StringPrototypeSmall, 0, kReceiver) \
/* ES6 #sec-string.prototype.split */ \
TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.strike */ \
TFJ(StringPrototypeStrike, 0, kReceiver) \
/* ES6 #sec-string.prototype.sub */ \
TFJ(StringPrototypeSub, 0, kReceiver) \
/* ES6 #sec-string.prototype.substr */ \
TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substring */ \
TFJ(StringPrototypeSubstring, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.sup */ \
TFJ(StringPrototypeSup, 0, kReceiver) \
/* ES6 #sec-string.prototype.tostring */ \
TFJ(StringPrototypeToString, 0, kReceiver) \
TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \

View File

@ -131,10 +131,10 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
}
TF_BUILTIN(StringPrototypeToLowerCaseIntl, IntlBuiltinsAssembler) {
Node* const maybe_string = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
TNode<Object> maybe_string = CAST(Parameter(Descriptor::kReceiver));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* const string =
TNode<String> string =
ToThisString(context, maybe_string, "String.prototype.toLowerCase");
Return(CallBuiltin(Builtins::kStringToLowerCaseIntl, context, string));

View File

@ -321,7 +321,7 @@ TF_BUILTIN(SubString, StringBuiltinsAssembler) {
}
void StringBuiltinsAssembler::GenerateStringAt(
char const* method_name, TNode<Context> context, Node* receiver,
char const* method_name, TNode<Context> context, TNode<Object> receiver,
TNode<Object> maybe_position, TNode<Object> default_return,
const StringAtAccessor& accessor) {
// Check that {receiver} is coercible to Object and convert it to a String.
@ -707,7 +707,7 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
// ES6 #sec-string.prototype.charat
TF_BUILTIN(StringPrototypeCharAt, StringBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* receiver = Parameter(Descriptor::kReceiver);
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition));
GenerateStringAt("String.prototype.charAt", context, receiver, maybe_position,
@ -722,7 +722,7 @@ TF_BUILTIN(StringPrototypeCharAt, StringBuiltinsAssembler) {
// ES6 #sec-string.prototype.charcodeat
TF_BUILTIN(StringPrototypeCharCodeAt, StringBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* receiver = Parameter(Descriptor::kReceiver);
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition));
GenerateStringAt("String.prototype.charCodeAt", context, receiver,
@ -737,7 +737,7 @@ TF_BUILTIN(StringPrototypeCharCodeAt, StringBuiltinsAssembler) {
// ES6 #sec-string.prototype.codepointat
TF_BUILTIN(StringPrototypeCodePointAt, StringBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* receiver = Parameter(Descriptor::kReceiver);
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> maybe_position = CAST(Parameter(Descriptor::kPosition));
GenerateStringAt("String.prototype.codePointAt", context, receiver,
@ -760,8 +760,8 @@ TF_BUILTIN(StringPrototypeConcat, CodeStubAssembler) {
CodeStubArguments arguments(
this,
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)));
Node* receiver = arguments.GetReceiver();
Node* context = Parameter(Descriptor::kContext);
TNode<Object> receiver = arguments.GetReceiver();
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
// Check that {receiver} is coercible to Object and convert it to a String.
receiver = ToThisString(context, receiver, "String.prototype.concat");
@ -1166,7 +1166,7 @@ TF_BUILTIN(StringPrototypeRepeat, StringBuiltinsAssembler) {
return_emptystring(this);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Node* const receiver = Parameter(Descriptor::kReceiver);
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
TNode<Object> count = CAST(Parameter(Descriptor::kCount));
Node* const string =
ToThisString(context, receiver, "String.prototype.repeat");
@ -1570,8 +1570,9 @@ class StringPadAssembler : public StringBuiltinsAssembler {
void Generate(Variant variant, const char* method_name, TNode<IntPtrT> argc,
TNode<Context> context) {
CodeStubArguments arguments(this, argc);
Node* const receiver = arguments.GetReceiver();
Node* const receiver_string = ToThisString(context, receiver, method_name);
TNode<Object> receiver = arguments.GetReceiver();
TNode<String> receiver_string =
ToThisString(context, receiver, method_name);
TNode<Smi> const string_length = LoadStringLengthAsSmi(receiver_string);
TVARIABLE(String, var_fill_string, StringConstant(" "));
@ -1939,7 +1940,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
Node* const receiver = args.GetReceiver();
TNode<Object> receiver = args.GetReceiver();
TNode<Object> start = args.GetOptionalArgumentValue(kStartArg);
TNode<Object> length = args.GetOptionalArgumentValue(kLengthArg);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
@ -2095,10 +2096,10 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
Node* const receiver = args.GetReceiver();
Node* const start = args.GetOptionalArgumentValue(kStartArg);
Node* const end = args.GetOptionalArgumentValue(kEndArg);
Node* const context = Parameter(Descriptor::kContext);
TNode<Object> receiver = args.GetReceiver();
TNode<Object> start = args.GetOptionalArgumentValue(kStartArg);
TNode<Object> end = args.GetOptionalArgumentValue(kEndArg);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Label out(this);
@ -2174,7 +2175,7 @@ void StringTrimAssembler::Generate(String::TrimMode mode,
Label return_emptystring(this), if_runtime(this);
CodeStubArguments arguments(this, argc);
Node* const receiver = arguments.GetReceiver();
TNode<Object> receiver = arguments.GetReceiver();
// Check that {receiver} is coercible to Object and convert it to a String.
TNode<String> const string = ToThisString(context, receiver, method_name);
@ -2332,8 +2333,8 @@ TF_BUILTIN(StringPrototypeValueOf, CodeStubAssembler) {
}
TF_BUILTIN(StringPrototypeIterator, CodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* string =
ToThisString(context, receiver, "String.prototype[Symbol.iterator]");
@ -2548,154 +2549,5 @@ TF_BUILTIN(StringToList, StringBuiltinsAssembler) {
Return(StringToList(context, string));
}
// -----------------------------------------------------------------------------
// ES6 section B.2.3 Additional Properties of the String.prototype object
class StringHtmlAssembler : public StringBuiltinsAssembler {
public:
explicit StringHtmlAssembler(compiler::CodeAssemblerState* state)
: StringBuiltinsAssembler(state) {}
protected:
void Generate(Node* const context, Node* const receiver,
const char* method_name, const char* tag_name) {
Node* const string = ToThisString(context, receiver, method_name);
std::string open_tag = "<" + std::string(tag_name) + ">";
std::string close_tag = "</" + std::string(tag_name) + ">";
Node* strings[] = {StringConstant(open_tag.c_str()), string,
StringConstant(close_tag.c_str())};
Return(ConcatStrings(context, strings, arraysize(strings)));
}
void GenerateWithAttribute(Node* const context, Node* const receiver,
const char* method_name, const char* tag_name,
const char* attr, Node* const value) {
Node* const string = ToThisString(context, receiver, method_name);
TNode<String> value_string =
EscapeQuotes(CAST(context), ToString_Inline(context, value));
std::string open_tag_attr =
"<" + std::string(tag_name) + " " + std::string(attr) + "=\"";
std::string close_tag = "</" + std::string(tag_name) + ">";
Node* strings[] = {StringConstant(open_tag_attr.c_str()), value_string,
StringConstant("\">"), string,
StringConstant(close_tag.c_str())};
Return(ConcatStrings(context, strings, arraysize(strings)));
}
Node* ConcatStrings(Node* const context, Node** strings, int len) {
VARIABLE(var_result, MachineRepresentation::kTagged, strings[0]);
for (int i = 1; i < len; i++) {
var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context,
var_result.value(), strings[i]));
}
return var_result.value();
}
TNode<String> EscapeQuotes(TNode<Context> context, TNode<String> string) {
return CAST(CallRuntime(Runtime::kStringEscapeQuotes, context, string));
}
};
// ES6 #sec-string.prototype.anchor
TF_BUILTIN(StringPrototypeAnchor, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
GenerateWithAttribute(context, receiver, "String.prototype.anchor", "a",
"name", value);
}
// ES6 #sec-string.prototype.big
TF_BUILTIN(StringPrototypeBig, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.big", "big");
}
// ES6 #sec-string.prototype.blink
TF_BUILTIN(StringPrototypeBlink, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.blink", "blink");
}
// ES6 #sec-string.prototype.bold
TF_BUILTIN(StringPrototypeBold, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.bold", "b");
}
// ES6 #sec-string.prototype.fontcolor
TF_BUILTIN(StringPrototypeFontcolor, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
GenerateWithAttribute(context, receiver, "String.prototype.fontcolor", "font",
"color", value);
}
// ES6 #sec-string.prototype.fontsize
TF_BUILTIN(StringPrototypeFontsize, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
GenerateWithAttribute(context, receiver, "String.prototype.fontsize", "font",
"size", value);
}
// ES6 #sec-string.prototype.fixed
TF_BUILTIN(StringPrototypeFixed, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.fixed", "tt");
}
// ES6 #sec-string.prototype.italics
TF_BUILTIN(StringPrototypeItalics, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.italics", "i");
}
// ES6 #sec-string.prototype.link
TF_BUILTIN(StringPrototypeLink, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const value = Parameter(Descriptor::kValue);
GenerateWithAttribute(context, receiver, "String.prototype.link", "a", "href",
value);
}
// ES6 #sec-string.prototype.small
TF_BUILTIN(StringPrototypeSmall, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.small", "small");
}
// ES6 #sec-string.prototype.strike
TF_BUILTIN(StringPrototypeStrike, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.strike", "strike");
}
// ES6 #sec-string.prototype.sub
TF_BUILTIN(StringPrototypeSub, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.sub", "sub");
}
// ES6 #sec-string.prototype.sup
TF_BUILTIN(StringPrototypeSup, StringHtmlAssembler) {
Node* const context = Parameter(Descriptor::kContext);
Node* const receiver = Parameter(Descriptor::kReceiver);
Generate(context, receiver, "String.prototype.sup", "sup");
}
} // namespace internal
} // namespace v8

View File

@ -68,7 +68,7 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
StringAtAccessor;
void GenerateStringAt(const char* method_name, TNode<Context> context,
Node* receiver, TNode<Object> maybe_position,
TNode<Object> receiver, TNode<Object> maybe_position,
TNode<Object> default_return,
const StringAtAccessor& accessor);

125
src/builtins/string-html.tq Normal file
View File

@ -0,0 +1,125 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace string_html {
extern runtime StringEscapeQuotes(Context, String): String;
// https://tc39.github.io/ecma262/#sec-createhtml
builtin CreateHTML(implicit context: Context)(
receiver: Object, methodName: String, tagName: String, attr: String,
attrValue: Object): String {
const tagContents: String = ToThisString(receiver, methodName);
let result = '<' + tagName;
if (attr != kEmptyString) {
const attrStringValue: String =
StringEscapeQuotes(context, ToString_Inline(context, attrValue));
result = result + ' ' + attr + '=\"' + attrStringValue + '\"';
}
return result + '>' + tagContents + '</' + tagName + '>';
}
// https://tc39.github.io/ecma262/#sec-string.prototype.anchor
javascript builtin StringPrototypeAnchor(
context: Context, receiver: Object, ...arguments): String {
return CreateHTML(
receiver, 'String.prototype.anchor', 'a', 'name', arguments[0]);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.big
javascript builtin
StringPrototypeBig(context: Context, receiver: Object, ...arguments): String {
return CreateHTML(
receiver, 'String.prototype.big', 'big', kEmptyString, kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.blink
javascript builtin
StringPrototypeBlink(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.blink', 'blink', kEmptyString,
kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.bold
javascript builtin
StringPrototypeBold(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.bold', 'b', kEmptyString, kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.fontcolor
javascript builtin
StringPrototypeFontcolor(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.fontcolor', 'font', 'color', arguments[0]);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.fontsize
javascript builtin
StringPrototypeFontsize(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.fontsize', 'font', 'size', arguments[0]);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.fixed
javascript builtin
StringPrototypeFixed(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.fixed', 'tt', kEmptyString, kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.italics
javascript builtin
StringPrototypeItalics(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.italics', 'i', kEmptyString, kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.link
javascript builtin
StringPrototypeLink(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.link', 'a', 'href', arguments[0]);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.small
javascript builtin
StringPrototypeSmall(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.small', 'small', kEmptyString,
kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.strike
javascript builtin
StringPrototypeStrike(context: Context, receiver: Object, ...arguments):
String {
return CreateHTML(
receiver, 'String.prototype.strike', 'strike', kEmptyString,
kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.sub
javascript builtin
StringPrototypeSub(context: Context, receiver: Object, ...arguments): String {
return CreateHTML(
receiver, 'String.prototype.sub', 'sub', kEmptyString, kEmptyString);
}
// https://tc39.github.io/ecma262/#sec-string.prototype.sup
javascript builtin
StringPrototypeSup(context: Context, receiver: Object, ...arguments): String {
return CreateHTML(
receiver, 'String.prototype.sup', 'sup', kEmptyString, kEmptyString);
}
}

View File

@ -5554,8 +5554,9 @@ TNode<Number> CodeStubAssembler::ChangeUintPtrToTagged(TNode<UintPtrT> value) {
return var_result.value();
}
TNode<String> CodeStubAssembler::ToThisString(Node* context, Node* value,
char const* method_name) {
TNode<String> CodeStubAssembler::ToThisString(TNode<Context> context,
TNode<Object> value,
TNode<String> method_name) {
VARIABLE(var_value, MachineRepresentation::kTagged, value);
// Check if the {value} is a Smi or a HeapObject.
@ -5565,7 +5566,7 @@ TNode<String> CodeStubAssembler::ToThisString(Node* context, Node* value,
BIND(&if_valueisnotsmi);
{
// Load the instance type of the {value}.
Node* value_instance_type = LoadInstanceType(value);
Node* value_instance_type = LoadInstanceType(CAST(value));
// Check if the {value} is already String.
Label if_valueisnotstring(this, Label::kDeferred);

View File

@ -2030,8 +2030,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Type conversions.
// Throws a TypeError for {method_name} if {value} is not coercible to Object,
// or returns the {value} converted to a String otherwise.
TNode<String> ToThisString(Node* context, Node* value,
char const* method_name);
TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
TNode<String> method_name);
TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
char const* method_name) {
return ToThisString(context, value, StringConstant(method_name));
}
// Throws a TypeError for {method_name} if {value} is neither of the given
// {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or
// returns the {value} (or wrapped value) otherwise.

View File

@ -949,6 +949,7 @@ static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
case Builtins::kFlattenIntoArray:
case Builtins::kGetProperty:
case Builtins::kHasProperty:
case Builtins::kCreateHTML:
case Builtins::kNonNumberToNumber:
case Builtins::kNonPrimitiveToPrimitive_Number:
case Builtins::kNumberToString: