| Index: src/runtime/runtime-strings.cc | 
| diff --git a/src/runtime/runtime-strings.cc b/src/runtime/runtime-strings.cc | 
| index 2477eb70b9026a5256563b19c9bed124643a44c8..2923c0416123c90e608e5916b5a863e2c0407f89 100644 | 
| --- a/src/runtime/runtime-strings.cc | 
| +++ b/src/runtime/runtime-strings.cc | 
| @@ -5,6 +5,7 @@ | 
| #include "src/runtime/runtime-utils.h" | 
|  | 
| #include "src/arguments.h" | 
| +#include "src/char-predicates-inl.h" | 
| #include "src/regexp/jsregexp-inl.h" | 
| #include "src/string-builder.h" | 
| #include "src/string-search.h" | 
| @@ -1151,6 +1152,132 @@ RUNTIME_FUNCTION(Runtime_NewString) { | 
| return *result; | 
| } | 
|  | 
| +// anonymous namespace for URIEncode helper functions | 
| +namespace { | 
| + | 
| +bool IsUnescapePredicateInUriComponent(uc16 c) { | 
| +  if (IsAlphaNumeric(c)) { | 
| +    return true; | 
| +  } | 
| + | 
| +  switch (c) { | 
| +    case '!': | 
| +    case '\'': | 
| +    case '(': | 
| +    case ')': | 
| +    case '*': | 
| +    case '-': | 
| +    case '.': | 
| +    case '_': | 
| +    case '~': | 
| +      return true; | 
| +    default: | 
| +      return false; | 
| +  } | 
| +} | 
| + | 
| +bool IsUriSeparator(uc16 c) { | 
| +  switch (c) { | 
| +    case '#': | 
| +    case ':': | 
| +    case ';': | 
| +    case '/': | 
| +    case '?': | 
| +    case '$': | 
| +    case '&': | 
| +    case '+': | 
| +    case ',': | 
| +    case '@': | 
| +    case '=': | 
| +      return true; | 
| +    default: | 
| +      return false; | 
| +  } | 
| +} | 
| + | 
| +void AddHexEncodedToBuffer(uint8_t octet, List<uint8_t>* buffer) { | 
| +  buffer->Add('%'); | 
| +  buffer->Add(HexCharOfValue(octet >> 4)); | 
| +  buffer->Add(HexCharOfValue(octet & 0x0F)); | 
| +} | 
| + | 
| +void EncodeSingle(uc16 c, List<uint8_t>* buffer) { | 
| +  uint8_t x = (c >> 12) & 0xF; | 
| +  uint8_t y = (c >> 6) & 63; | 
| +  uint8_t z = c & 63; | 
| +  if (c <= 0x007F) { | 
| +    AddHexEncodedToBuffer(c, buffer); | 
| +  } else if (c <= 0x07FF) { | 
| +    AddHexEncodedToBuffer(y + 192, buffer); | 
| +    AddHexEncodedToBuffer(z + 128, buffer); | 
| +  } else { | 
| +    AddHexEncodedToBuffer(x + 224, buffer); | 
| +    AddHexEncodedToBuffer(y + 128, buffer); | 
| +    AddHexEncodedToBuffer(z + 128, buffer); | 
| +  } | 
| +} | 
| + | 
| +void EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) { | 
| +  uint8_t u = ((cc1 >> 6) & 0xF) + 1; | 
| +  uint8_t w = (cc1 >> 2) & 0xF; | 
| +  uint8_t x = cc1 & 3; | 
| +  uint8_t y = (cc2 >> 6) & 0xF; | 
| +  uint8_t z = cc2 & 63; | 
| +  AddHexEncodedToBuffer((u >> 2) + 240, buffer); | 
| +  AddHexEncodedToBuffer((((u & 3) << 4) | w) + 128, buffer); | 
| +  AddHexEncodedToBuffer(((x << 4) | y) + 128, buffer); | 
| +  AddHexEncodedToBuffer(z + 128, buffer); | 
| +} | 
| + | 
| +}  // anonymous namespace | 
| + | 
| +RUNTIME_FUNCTION(Runtime_URIEncode) { | 
| +  HandleScope scope(isolate); | 
| +  DCHECK(args.length() == 2); | 
| +  CONVERT_ARG_HANDLE_CHECKED(String, uri, 0); | 
| +  CONVERT_BOOLEAN_ARG_CHECKED(is_uri, 1); | 
| + | 
| +  uri = String::Flatten(uri); | 
| +  int uri_length = uri->length(); | 
| +  List<uint8_t> buffer(uri_length); | 
| + | 
| +  { | 
| +    DisallowHeapAllocation no_gc; | 
| +    String::FlatContent uri_content = uri->GetFlatContent(); | 
| + | 
| +    for (int k = 0; k < uri_length; k++) { | 
| +      uc16 cc1 = uri_content.Get(k); | 
| +      if (unibrow::Utf16::IsLeadSurrogate(cc1)) { | 
| +        k++; | 
| +        if (k < uri_length) { | 
| +          uc16 cc2 = uri->Get(k); | 
| +          if (unibrow::Utf16::IsTrailSurrogate(cc2)) { | 
| +            EncodePair(cc1, cc2, &buffer); | 
| +            continue; | 
| +          } | 
| +        } | 
| +      } else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) { | 
| +        if (IsUnescapePredicateInUriComponent(cc1) || | 
| +            (is_uri && IsUriSeparator(cc1))) { | 
| +          buffer.Add(cc1); | 
| +        } else { | 
| +          EncodeSingle(cc1, &buffer); | 
| +        } | 
| +        continue; | 
| +      } | 
| + | 
| +      AllowHeapAllocation allocate_error_and_return; | 
| +      THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewURIError()); | 
| +    } | 
| +  } | 
| + | 
| +  Handle<String> result; | 
| +  ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
| +      isolate, result, | 
| +      isolate->factory()->NewStringFromOneByte(buffer.ToConstVector())); | 
| +  return *result; | 
| +} | 
| + | 
| RUNTIME_FUNCTION(Runtime_StringLessThan) { | 
| HandleScope handle_scope(isolate); | 
| DCHECK_EQ(2, args.length()); | 
|  |