Commit 8dfdeae0 authored by peterwmwong's avatar peterwmwong Committed by Commit Bot

[builtins] Convert String HTML functions (ex. anchor, big, bold) to CSA

  - Added TFJ builtins for S.p.{anchor, big, blink, bold, fontcolor,
      fontsize, fixed, italics, link, small, strike, sub, sup}
  - Removed functionality from string.js

Bug: v8:5049
Change-Id: I3a91b52eaceef5c47bb55ed62780d72ef1e802e9
Reviewed-on: https://chromium-review.googlesource.com/666487
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48056}
parent 3d046986
......@@ -1939,6 +1939,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
DONT_ENUM);
// Install the String.prototype methods.
SimpleInstallFunction(prototype, "anchor", Builtins::kStringPrototypeAnchor,
1, true);
SimpleInstallFunction(prototype, "big", Builtins::kStringPrototypeBig, 0,
true);
SimpleInstallFunction(prototype, "blink", Builtins::kStringPrototypeBlink,
0, true);
SimpleInstallFunction(prototype, "bold", Builtins::kStringPrototypeBold, 0,
true);
SimpleInstallFunction(prototype, "charAt", Builtins::kStringPrototypeCharAt,
1, true);
SimpleInstallFunction(prototype, "charCodeAt",
......@@ -1949,12 +1957,22 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
1, false);
SimpleInstallFunction(prototype, "endsWith",
Builtins::kStringPrototypeEndsWith, 1, false);
SimpleInstallFunction(prototype, "fontcolor",
Builtins::kStringPrototypeFontcolor, 1, true);
SimpleInstallFunction(prototype, "fontsize",
Builtins::kStringPrototypeFontsize, 1, true);
SimpleInstallFunction(prototype, "fixed", Builtins::kStringPrototypeFixed,
0, true);
SimpleInstallFunction(prototype, "includes",
Builtins::kStringPrototypeIncludes, 1, false);
SimpleInstallFunction(prototype, "indexOf",
Builtins::kStringPrototypeIndexOf, 1, false);
SimpleInstallFunction(prototype, "italics",
Builtins::kStringPrototypeItalics, 0, true);
SimpleInstallFunction(prototype, "lastIndexOf",
Builtins::kStringPrototypeLastIndexOf, 1, false);
SimpleInstallFunction(prototype, "link", Builtins::kStringPrototypeLink, 1,
true);
SimpleInstallFunction(prototype, "localeCompare",
Builtins::kStringPrototypeLocaleCompare, 1, true);
#ifdef V8_INTL_SUPPORT
......@@ -1970,12 +1988,20 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kStringPrototypeReplace, 2, true);
SimpleInstallFunction(prototype, "slice", Builtins::kStringPrototypeSlice,
2, false);
SimpleInstallFunction(prototype, "small", Builtins::kStringPrototypeSmall,
0, true);
SimpleInstallFunction(prototype, "split", Builtins::kStringPrototypeSplit,
2, false);
SimpleInstallFunction(prototype, "strike", Builtins::kStringPrototypeStrike,
0, true);
SimpleInstallFunction(prototype, "sub", Builtins::kStringPrototypeSub, 0,
true);
SimpleInstallFunction(prototype, "substr", Builtins::kStringPrototypeSubstr,
2, false);
SimpleInstallFunction(prototype, "substring",
Builtins::kStringPrototypeSubstring, 2, false);
SimpleInstallFunction(prototype, "sup", Builtins::kStringPrototypeSup, 0,
true);
SimpleInstallFunction(prototype, "startsWith",
Builtins::kStringPrototypeStartsWith, 1, false);
SimpleInstallFunction(prototype, "toString",
......
......@@ -894,6 +894,14 @@ namespace internal {
CPP(StringFromCodePoint) \
/* ES6 #sec-string.fromcharcode */ \
TFJ(StringFromCharCode, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.anchor */ \
TFJ(StringPrototypeAnchor, 1, kValue) \
/* ES6 #sec-string.prototype.big */ \
TFJ(StringPrototypeBig, 0) \
/* ES6 #sec-string.prototype.blink */ \
TFJ(StringPrototypeBlink, 0) \
/* ES6 #sec-string.prototype.bold */ \
TFJ(StringPrototypeBold, 0) \
/* ES6 #sec-string.prototype.charat */ \
TFJ(StringPrototypeCharAt, 1, kPosition) \
/* ES6 #sec-string.prototype.charcodeat */ \
......@@ -904,13 +912,23 @@ namespace internal {
TFJ(StringPrototypeConcat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.endswith */ \
CPP(StringPrototypeEndsWith) \
/* ES6 #sec-string.prototype.fontcolor */ \
TFJ(StringPrototypeFontcolor, 1, kValue) \
/* ES6 #sec-string.prototype.fontsize */ \
TFJ(StringPrototypeFontsize, 1, kValue) \
/* ES6 #sec-string.prototype.fixed */ \
TFJ(StringPrototypeFixed, 0) \
/* 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) \
/* ES6 #sec-string.prototype.lastindexof */ \
CPP(StringPrototypeLastIndexOf) \
/* ES6 #sec-string.prototype.link */ \
TFJ(StringPrototypeLink, 1, kValue) \
/* ES6 #sec-string.prototype.localecompare */ \
CPP(StringPrototypeLocaleCompare) \
/* ES6 #sec-string.prototype.repeat */ \
......@@ -919,13 +937,21 @@ namespace internal {
TFJ(StringPrototypeReplace, 2, kSearch, kReplace) \
/* ES6 #sec-string.prototype.slice */ \
TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.small */ \
TFJ(StringPrototypeSmall, 0) \
/* ES6 #sec-string.prototype.split */ \
TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.strike */ \
TFJ(StringPrototypeStrike, 0) \
/* ES6 #sec-string.prototype.sub */ \
TFJ(StringPrototypeSub, 0) \
/* 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) \
/* ES6 #sec-string.prototype.startswith */ \
CPP(StringPrototypeStartsWith) \
/* ES6 #sec-string.prototype.tostring */ \
......
......@@ -2154,5 +2154,166 @@ TF_BUILTIN(StringIteratorPrototypeNext, StringBuiltinsAssembler) {
}
}
// -----------------------------------------------------------------------------
// 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);
Node* const value_string =
EscapeQuotes(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();
}
Node* EscapeQuotes(Node* const context, Node* const string) {
CSA_ASSERT(this, IsString(string));
Node* const regexp_function = LoadContextElement(
LoadNativeContext(context), Context::REGEXP_FUNCTION_INDEX);
Node* const initial_map = LoadObjectField(
regexp_function, JSFunction::kPrototypeOrInitialMapOffset);
// TODO(pwong): Refactor to not allocate RegExp
Node* const regexp =
CallRuntime(Runtime::kRegExpInitializeAndCompile, context,
AllocateJSObjectFromMap(initial_map), StringConstant("\""),
StringConstant("g"));
return CallRuntime(Runtime::kRegExpInternalReplace, context, regexp, string,
StringConstant("&quot;"));
}
};
// 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
......@@ -306,6 +306,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(StringCharCodeAt) \
V(StringIndexOfUnchecked) \
V(StringEqual) \
V(RegExpInitializeAndCompile) \
V(SymbolDescriptiveString) \
V(GenerateRandomNumbers) \
V(GlobalPrint) \
......@@ -588,19 +589,32 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
case Builtins::kStringFromCharCode:
case Builtins::kStringFromCodePoint:
case Builtins::kStringConstructor:
case Builtins::kStringPrototypeAnchor:
case Builtins::kStringPrototypeBig:
case Builtins::kStringPrototypeBlink:
case Builtins::kStringPrototypeBold:
case Builtins::kStringPrototypeCharAt:
case Builtins::kStringPrototypeCharCodeAt:
case Builtins::kStringPrototypeCodePointAt:
case Builtins::kStringPrototypeConcat:
case Builtins::kStringPrototypeEndsWith:
case Builtins::kStringPrototypeFixed:
case Builtins::kStringPrototypeFontcolor:
case Builtins::kStringPrototypeFontsize:
case Builtins::kStringPrototypeIncludes:
case Builtins::kStringPrototypeIndexOf:
case Builtins::kStringPrototypeItalics:
case Builtins::kStringPrototypeLastIndexOf:
case Builtins::kStringPrototypeLink:
case Builtins::kStringPrototypeRepeat:
case Builtins::kStringPrototypeSlice:
case Builtins::kStringPrototypeSmall:
case Builtins::kStringPrototypeStartsWith:
case Builtins::kStringPrototypeStrike:
case Builtins::kStringPrototypeSub:
case Builtins::kStringPrototypeSubstr:
case Builtins::kStringPrototypeSubstring:
case Builtins::kStringPrototypeSup:
case Builtins::kStringPrototypeToString:
#ifndef V8_INTL_SUPPORT
case Builtins::kStringPrototypeToLowerCase:
......
......@@ -17,11 +17,6 @@ var searchSymbol = utils.ImportNow("search_symbol");
//-------------------------------------------------------------------
// ES#sec-createhtml
function HtmlEscape(str) {
return %RegExpInternalReplace(/"/g, TO_STRING(str), "&quot;");
}
// Set up the non-enumerable functions on the String prototype object.
DEFINE_METHODS(
GlobalString.prototype,
......@@ -61,87 +56,6 @@ DEFINE_METHODS(
var regexp = %RegExpCreate(pattern);
return %_Call(regexp[searchSymbol], regexp, subject);
}
/* ES#sec-string.prototype.anchor */
anchor(name) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.anchor");
return "<a name=\"" + HtmlEscape(name) + "\">" + TO_STRING(this) +
"</a>";
}
/* ES#sec-string.prototype.big */
big() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.big");
return "<big>" + TO_STRING(this) + "</big>";
}
/* ES#sec-string.prototype.blink */
blink() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.blink");
return "<blink>" + TO_STRING(this) + "</blink>";
}
/* ES#sec-string.prototype.bold */
bold() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.bold");
return "<b>" + TO_STRING(this) + "</b>";
}
/* ES#sec-string.prototype.fixed */
fixed() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fixed");
return "<tt>" + TO_STRING(this) + "</tt>";
}
/* ES#sec-string.prototype.fontcolor */
fontcolor(color) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontcolor");
return "<font color=\"" + HtmlEscape(color) + "\">" + TO_STRING(this) +
"</font>";
}
/* ES#sec-string.prototype.fontsize */
fontsize(size) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontsize");
return "<font size=\"" + HtmlEscape(size) + "\">" + TO_STRING(this) +
"</font>";
}
/* ES#sec-string.prototype.italics */
italics() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.italics");
return "<i>" + TO_STRING(this) + "</i>";
}
/* ES#sec-string.prototype.link */
link(s) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.link");
return "<a href=\"" + HtmlEscape(s) + "\">" + TO_STRING(this) + "</a>";
}
/* ES#sec-string.prototype.small */
small() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.small");
return "<small>" + TO_STRING(this) + "</small>";
}
/* ES#sec-string.prototype.strike */
strike() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.strike");
return "<strike>" + TO_STRING(this) + "</strike>";
}
/* ES#sec-string.prototype.sub */
sub() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.sub");
return "<sub>" + TO_STRING(this) + "</sub>";
}
/* ES#sec-string.prototype.sup */
sup() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.sup");
return "<sup>" + TO_STRING(this) + "</sup>";
}
}
);
......
......@@ -8,7 +8,8 @@
assertEquals('_'.anchor('b'), '<a name="b">_</a>');
assertEquals('<'.anchor('<'), '<a name="<"><</a>');
assertEquals('_'.anchor(0x2A), '<a name="42">_</a>');
assertEquals('_'.anchor('\x22'), '<a name="&quot;">_</a>');
assertEquals('_'.anchor('\x22\x22'), '<a name="&quot;&quot;">_</a>');
assertEquals('_'.anchor(), '<a name="undefined">_</a>');
assertEquals(String.prototype.anchor.call(0x2A, 0x2A), '<a name="42">42</a>');
assertThrows(function() {
String.prototype.anchor.call(undefined);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment