'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'],
'os:cygwin': ['platform-cygwin.cc', 'platform-posix.cc'],
'os:nullos': ['platform-nullos.cc'],
- 'os:win32': ['platform-win32.cc'],
+ 'os:win32': ['platform-win32.cc', 'win32-math.cc'],
'mode:release': [],
'mode:debug': [
'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
PREPARSER_SOURCES = {
'all': Split("""
allocation.cc
+ bignum.cc
+ bignum-dtoa.cc
+ cached-powers.cc
+ conversions.cc
+ diy-fp.cc
+ dtoa.cc
+ fast-dtoa.cc
+ fixed-dtoa.cc
hashmap.cc
preparse-data.cc
preparser.cc
preparser-api.cc
scanner-base.cc
+ strtod.cc
token.cc
unicode.cc
utils.cc
- """)
+ """),
+ 'os:win32': ['win32-math.cc']
}
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
#include <math.h>
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "checks.h"
+#include "utils.h"
+
#include "bignum-dtoa.h"
#include "bignum.h"
#include <math.h>
#include <float.h> // Required for DBL_MAX and on Win32 for finite()
#include <stdarg.h>
+#include "globals.h" // Required for V8_INFINITY
// ----------------------------------------------------------------------------
// Extra POSIX/ANSI functions for Win32/MSVC.
#include "conversions.h"
#include "strtod.h"
#include "platform.h"
+#include "double.h"
namespace v8 {
namespace internal {
int32_t DoubleToInt32(double x) {
int32_t i = FastD2I(x);
if (FastI2D(i) == x) return i;
- static const double two32 = 4294967296.0;
- static const double two31 = 2147483648.0;
- if (!isfinite(x) || x == 0) return 0;
- if (x < 0 || x >= two32) x = modulo(x, two32);
- x = (x >= 0) ? floor(x) : ceil(x) + two32;
- return (int32_t) ((x >= two31) ? x - two32 : x);
+ Double d(x);
+ int exponent = d.Exponent();
+ if (exponent < 0) {
+ if (exponent <= -Double::kSignificandSize) return 0;
+ return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
+ } else {
+ if (exponent > 31) return 0;
+ return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
+ }
}
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
+#include <math.h>
#include <limits.h>
#include "conversions-inl.h"
namespace internal {
-
double StringToDouble(UnicodeCache* unicode_cache,
const char* str, int flags, double empty_string_val) {
const char* end = str + StrLength(str);
int integer_pos = kBufferSize - 2;
do {
integer_buffer[integer_pos--] =
- chars[static_cast<int>(modulo(integer_part, radix))];
+ chars[static_cast<int>(fmod(integer_part, radix))];
integer_part /= radix;
} while (integer_part >= 1.0);
// Sanity check.
int flags,
double empty_string_val = 0);
+const int kDoubleToCStringMinBufferSize = 100;
+
// Converts a double to a string value according to ECMA-262 9.8.1.
// The buffer should be large enough for any floating point number.
// 100 characters is enough.
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
#include <math.h>
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "checks.h"
+#include "utils.h"
+
#include "dtoa.h"
#include "bignum-dtoa.h"
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "checks.h"
+#include "utils.h"
#include "fast-dtoa.h"
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
#include <math.h>
-#include "v8.h"
+#include "../include/v8stdint.h"
+#include "checks.h"
+#include "utils.h"
#include "double.h"
#include "fixed-dtoa.h"
#ifndef V8_GLOBALS_H_
#define V8_GLOBALS_H_
+// Define V8_INFINITY
+#define V8_INFINITY INFINITY
+
+// GCC specific stuff
+#ifdef __GNUC__
+
+#define __GNUC_VERSION_FOR_INFTY__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
+
+// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
+// warning flag and certain versions of GCC due to a bug:
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
+// For now, we use the more involved template-based version from <limits>, but
+// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
+// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
+#if __GNUC_VERSION_FOR_INFTY__ >= 29600 && __GNUC_VERSION_FOR_INFTY__ < 40100
+#include <limits>
+#undef V8_INFINITY
+#define V8_INFINITY std::numeric_limits<double>::infinity()
+#endif
+#undef __GNUC_VERSION_FOR_INFTY__
+
+#endif // __GNUC__
+
+#ifdef _MSC_VER
+#undef V8_INFINITY
+#define V8_INFINITY HUGE_VAL
+#endif
+
+
#include "../include/v8stdint.h"
namespace v8 {
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
#include "platform.h"
#include "vm-state-inl.h"
-// Extra POSIX/ANSI routines for Win32 when when using Visual Studio C++. Please
-// refer to The Open Group Base Specification for specification of the correct
-// semantics for these functions.
-// (http://www.opengroup.org/onlinepubs/000095399/)
#ifdef _MSC_VER
-namespace v8 {
-namespace internal {
-
-// Test for finite value - usually defined in math.h
-int isfinite(double x) {
- return _finite(x);
-}
-
-} // namespace v8
-} // namespace internal
-
-// Test for a NaN (not a number) value - usually defined in math.h
-int isnan(double x) {
- return _isnan(x);
-}
-
-
-// Test for infinity - usually defined in math.h
-int isinf(double x) {
- return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0;
-}
-
-
-// Test if x is less than y and both nominal - usually defined in math.h
-int isless(double x, double y) {
- return isnan(x) || isnan(y) ? 0 : x < y;
-}
-
-
-// Test if x is greater than y and both nominal - usually defined in math.h
-int isgreater(double x, double y) {
- return isnan(x) || isnan(y) ? 0 : x > y;
-}
-
-
-// Classify floating point number - usually defined in math.h
-int fpclassify(double x) {
- // Use the MS-specific _fpclass() for classification.
- int flags = _fpclass(x);
-
- // Determine class. We cannot use a switch statement because
- // the _FPCLASS_ constants are defined as flags.
- if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL;
- if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO;
- if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL;
- if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE;
-
- // All cases should be covered by the code above.
- ASSERT(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN));
- return FP_NAN;
-}
-
-
-// Test sign - usually defined in math.h
-int signbit(double x) {
- // We need to take care of the special case of both positive
- // and negative versions of zero.
- if (x == 0)
- return _fpclass(x) & _FPCLASS_NZ;
- else
- return x < 0;
-}
-
-
// Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually
// defined in strings.h.
int strncasecmp(const char* s1, const char* s2, int n) {
#ifndef V8_PLATFORM_H_
#define V8_PLATFORM_H_
-#define V8_INFINITY INFINITY
+#ifdef __sun
+# ifndef signbit
+int signbit(double x);
+# endif
+#endif
+
+// GCC specific stuff
+#ifdef __GNUC__
+
+// Needed for va_list on at least MinGW and Android.
+#include <stdarg.h>
+
+#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
+
+#endif // __GNUC__
+
// Windows specific stuff.
#ifdef WIN32
// Microsoft Visual C++ specific stuff.
#ifdef _MSC_VER
-enum {
- FP_NAN,
- FP_INFINITE,
- FP_ZERO,
- FP_SUBNORMAL,
- FP_NORMAL
-};
-
-#undef V8_INFINITY
-#define V8_INFINITY HUGE_VAL
-
-namespace v8 {
-namespace internal {
-int isfinite(double x);
-} }
-int isnan(double x);
-int isinf(double x);
-int isless(double x, double y);
-int isgreater(double x, double y);
-int fpclassify(double x);
-int signbit(double x);
+#include "win32-math.h"
int strncasecmp(const char* s1, const char* s2, int n);
#endif // WIN32
-
-#ifdef __sun
-# ifndef signbit
-int signbit(double x);
-# endif
-#endif
-
-
-// GCC specific stuff
-#ifdef __GNUC__
-
-// Needed for va_list on at least MinGW and Android.
-#include <stdarg.h>
-
-#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
-
-// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
-// warning flag and certain versions of GCC due to a bug:
-// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
-// For now, we use the more involved template-based version from <limits>, but
-// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
-// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
-#if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
-#include <limits>
-#undef V8_INFINITY
-#define V8_INFINITY std::numeric_limits<double>::infinity()
-#endif
-
-#endif // __GNUC__
-
#include "atomicops.h"
#include "platform-tls.h"
#include "utils.h"
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef _MSC_VER
+#define V8_WIN32_LEAN_AND_MEAN
+#include "win32-headers.h"
+#endif
+
#include "../include/v8-preparser.h"
#include "globals.h"
-#include "flags.h"
#include "checks.h"
#include "allocation.h"
#include "utils.h"
#include "list.h"
+#include "hashmap.h"
#include "scanner-base.h"
#include "preparse-data-format.h"
#include "preparse-data.h"
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <math.h>
+
#include "../include/v8stdint.h"
#include "unicode.h"
#include "globals.h"
#include "allocation.h"
#include "utils.h"
#include "list.h"
+#include "conversions.h"
+#include "hashmap.h"
#include "scanner-base.h"
#include "preparse-data-format.h"
#include "conversions-inl.h"
namespace v8 {
+
+#ifdef _MSC_VER
+// Usually defined in math.h, but not in MSVC.
+// Abstracted to work
+int isfinite(double value);
+#endif
+
namespace preparser {
// Preparsing checks a JavaScript program and emits preparse-data that helps
// Four of the tokens are treated specially
switch (token) {
case i::Token::EOS:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_eos", NULL);
+ return ReportMessageAt(source_location, "unexpected_eos", NULL);
case i::Token::NUMBER:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token_number", NULL);
+ return ReportMessageAt(source_location, "unexpected_token_number", NULL);
case i::Token::STRING:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token_string", NULL);
+ return ReportMessageAt(source_location, "unexpected_token_string", NULL);
case i::Token::IDENTIFIER:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+ return ReportMessageAt(source_location,
"unexpected_token_identifier", NULL);
case i::Token::FUTURE_RESERVED_WORD:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_reserved", NULL);
+ return ReportMessageAt(source_location, "unexpected_reserved", NULL);
case i::Token::FUTURE_STRICT_RESERVED_WORD:
- return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
+ return ReportMessageAt(source_location,
"unexpected_strict_reserved", NULL);
default:
const char* name = i::Token::String(token);
- ReportMessageAt(source_location.beg_pos, source_location.end_pos,
- "unexpected_token", name);
+ ReportMessageAt(source_location, "unexpected_token", name);
}
}
void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
i::Scanner::Location octal = scanner_->octal_position();
if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
- ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL);
+ ReportMessageAt(octal, "strict_octal_literal", NULL);
scanner_->clear_octal_position();
*ok = false;
}
if (identifier.IsFutureStrictReserved()) {
type = "strict_reserved_word";
}
- ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
+ ReportMessageAt(location, type, NULL);
*ok = false;
}
return Statement::FunctionDeclaration();
} else if (peek() == i::Token::CONST) {
if (strict_mode()) {
i::Scanner::Location location = scanner_->peek_location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "strict_const", NULL);
+ ReportMessageAt(location, "strict_const", NULL);
*ok = false;
return Statement::Default();
}
Expect(i::Token::WITH, CHECK_OK);
if (strict_mode()) {
i::Scanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "strict_mode_with", NULL);
+ ReportMessageAt(location, "strict_mode_with", NULL);
*ok = false;
return Statement::Default();
}
Expect(i::Token::THROW, CHECK_OK);
if (scanner_->HasAnyLineTerminatorBeforeNext()) {
i::JavaScriptScanner::Location pos = scanner_->location();
- ReportMessageAt(pos.beg_pos, pos.end_pos,
- "newline_after_throw", NULL);
+ ReportMessageAt(pos, "newline_after_throw", NULL);
*ok = false;
return Statement::Default();
}
if (strict_mode()) {
Next();
i::Scanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "strict_reserved_word", NULL);
+ ReportMessageAt(location, "strict_reserved_word", NULL);
*ok = false;
return Expression::Default();
}
return Expression::Default();
}
+void PreParser::CheckDuplicate(DuplicateFinder* finder,
+ i::Token::Value property,
+ int type,
+ bool* ok) {
+ int old_type;
+ if (property == i::Token::NUMBER) {
+ old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
+ } else if (scanner_->is_literal_ascii()) {
+ old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
+ type);
+ } else {
+ old_type = finder->AddUC16Symbol(scanner_->literal_uc16_string(), type);
+ }
+ if (HasConflict(old_type, type)) {
+ if (IsDataDataConflict(old_type, type)) {
+ // Both are data properties.
+ if (!strict_mode()) return;
+ ReportMessageAt(scanner_->location(),
+ "strict_duplicate_property", NULL);
+ } else if (IsDataAccessorConflict(old_type, type)) {
+ // Both a data and an accessor property with the same name.
+ ReportMessageAt(scanner_->location(),
+ "accessor_data_property", NULL);
+ } else {
+ ASSERT(IsAccessorAccessorConflict(old_type, type));
+ // Both accessors of the same type.
+ ReportMessageAt(scanner_->location(),
+ "accessor_get_set", NULL);
+ }
+ *ok = false;
+ }
+}
+
PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
// ObjectLiteral ::
// )*[','] '}'
Expect(i::Token::LBRACE, CHECK_OK);
+ DuplicateFinder duplicate_finder(scanner_->unicode_cache());
while (peek() != i::Token::RBRACE) {
i::Token::Value next = peek();
switch (next) {
if (!is_keyword) {
LogSymbol();
}
+ PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
+ CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
ParseFunctionLiteral(CHECK_OK);
if (peek() != i::Token::RBRACE) {
Expect(i::Token::COMMA, CHECK_OK);
}
continue; // restart the while
}
+ CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
break;
}
case i::Token::STRING:
Consume(next);
+ CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
GetStringSymbol();
break;
case i::Token::NUMBER:
Consume(next);
+ CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
break;
default:
if (i::Token::IsKeyword(next)) {
Consume(next);
+ CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
} else {
// Unexpected token.
*ok = false;
bool* ok) {
if (!scanner_->ScanRegExpPattern(seen_equal)) {
Next();
- i::JavaScriptScanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "unterminated_regexp", NULL);
+ ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
*ok = false;
return Expression::Default();
}
if (!scanner_->ScanRegExpFlags()) {
Next();
- i::JavaScriptScanner::Location location = scanner_->location();
- ReportMessageAt(location.beg_pos, location.end_pos,
- "invalid_regexp_flags", NULL);
+ ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
*ok = false;
return Expression::Default();
}
Expect(i::Token::LPAREN, CHECK_OK);
int start_position = scanner_->location().beg_pos;
bool done = (peek() == i::Token::RPAREN);
+ DuplicateFinder duplicate_finder(scanner_->unicode_cache());
while (!done) {
Identifier id = ParseIdentifier(CHECK_OK);
if (!id.IsValidStrictVariable()) {
id,
CHECK_OK);
}
+ int prev_value;
+ if (scanner_->is_literal_ascii()) {
+ prev_value =
+ duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
+ } else {
+ prev_value =
+ duplicate_finder.AddUC16Symbol(scanner_->literal_uc16_string(), 1);
+ }
+
+ if (prev_value != 0) {
+ SetStrictModeViolation(scanner_->location(),
+ "strict_param_dupe",
+ CHECK_OK);
+ }
done = (peek() == i::Token::RPAREN);
if (!done) {
Expect(i::Token::COMMA, CHECK_OK);
const char* type,
bool* ok) {
if (strict_mode()) {
- ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
+ ReportMessageAt(location, type, NULL);
*ok = false;
return;
}
// Delay report in case this later turns out to be strict code
// (i.e., for function names and parameters prior to a "use strict"
// directive).
+ // It's safe to overwrite an existing violation.
+ // It's either from a function that turned out to be non-strict,
+ // or it's in the current function (and we just need to report
+ // one error), or it's in a unclosed nesting function that wasn't
+ // strict (otherwise we would already be in strict mode).
strict_mode_violation_location_ = location;
strict_mode_violation_type_ = type;
}
i::Scanner::Location location = strict_mode_violation_location_;
if (location.IsValid() &&
location.beg_pos > beg_pos && location.end_pos < end_pos) {
- ReportMessageAt(location.beg_pos, location.end_pos,
- strict_mode_violation_type_, NULL);
+ ReportMessageAt(location, strict_mode_violation_type_, NULL);
*ok = false;
}
- strict_mode_violation_location_ = i::Scanner::Location::invalid();
}
type = "strict_reserved_word";
}
if (strict_mode()) {
- ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
+ ReportMessageAt(location, type, NULL);
*ok = false;
return;
}
next == i::Token::FUTURE_RESERVED_WORD ||
next == i::Token::FUTURE_STRICT_RESERVED_WORD;
}
+
+
+int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
+ return AddSymbol(i::Vector<const byte>::cast(key), true, value);
+}
+
+int DuplicateFinder::AddUC16Symbol(i::Vector<const uint16_t> key, int value) {
+ return AddSymbol(i::Vector<const byte>::cast(key), false, value);
+}
+
+int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
+ bool is_ascii,
+ int value) {
+ uint32_t hash = Hash(key, is_ascii);
+ byte* encoding = BackupKey(key, is_ascii);
+ i::HashMap::Entry* entry = map_->Lookup(encoding, hash, true);
+ int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
+ entry->value =
+ reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
+ return old_value;
+}
+
+
+int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
+ ASSERT(key.length() > 0);
+ // Quick check for already being in canonical form.
+ if (IsNumberCanonical(key)) {
+ return AddAsciiSymbol(key, value);
+ }
+
+ int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
+ double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
+ int length;
+ const char* string;
+ if (!isfinite(double_value)) {
+ string = "Infinity";
+ length = 8; // strlen("Infinity");
+ } else {
+ string = DoubleToCString(double_value,
+ i::Vector<char>(number_buffer_, kBufferSize));
+ length = i::StrLength(string);
+ }
+ return AddAsciiSymbol(i::Vector<const char>(string, length), value);
+}
+
+
+bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
+ // Test for a safe approximation of number literals that are already
+ // in canonical form: max 15 digits, no leading zeroes, except an
+ // integer part that is a single zero, and no trailing zeros below
+ // the decimal point.
+ int pos = 0;
+ int length = number.length();
+ if (number.length() > 15) return false;
+ if (number[pos] == '0') {
+ pos++;
+ } else {
+ while (pos < length &&
+ static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
+ }
+ if (length == pos) return true;
+ if (number[pos] != '.') return false;
+ pos++;
+ bool invalid_last_digit = true;
+ while (pos < length) {
+ byte digit = number[pos] - '0';
+ if (digit > '9' - '0') return false;
+ invalid_last_digit = (digit == 0);
+ pos++;
+ }
+ return !invalid_last_digit;
+}
+
+
+uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
+ // Primitive hash function, almost identical to the one used
+ // for strings (except that it's seeded by the length and ASCII-ness).
+ int length = key.length();
+ uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
+ for (int i = 0; i < length; i++) {
+ uint32_t c = key[i];
+ hash = (hash + c) * 1025;
+ hash ^= (hash >> 6);
+ }
+ return hash;
+}
+
+
+bool DuplicateFinder::Match(void* first, void* second) {
+ // Decode lengths.
+ // Length + ASCII-bit is encoded as base 128, most significant heptet first,
+ // with a 8th bit being non-zero while there are more heptets.
+ // The value encodes the number of bytes following, and whether the original
+ // was ASCII.
+ byte* s1 = reinterpret_cast<byte*>(first);
+ byte* s2 = reinterpret_cast<byte*>(second);
+ uint32_t length_ascii_field = 0;
+ byte c1;
+ do {
+ c1 = *s1;
+ if (c1 != *s2) return false;
+ length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
+ s1++;
+ s2++;
+ } while ((c1 & 0x80) != 0);
+ int length = static_cast<int>(length_ascii_field >> 1);
+ return memcmp(s1, s2, length) == 0;
+}
+
+
+byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
+ bool is_ascii) {
+ uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
+ backing_store_.StartSequence();
+ // Emit ascii_length as base-128 encoded number, with the 7th bit set
+ // on the byte of every heptet except the last, least significant, one.
+ if (ascii_length >= (1 << 7)) {
+ if (ascii_length >= (1 << 14)) {
+ if (ascii_length >= (1 << 21)) {
+ if (ascii_length >= (1 << 28)) {
+ backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
+ }
+ backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
+ }
+ backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
+ }
+ backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
+ }
+ backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
+
+ backing_store_.AddBlock(bytes);
+ return backing_store_.EndSequence().start();
+}
} } // v8::preparser
namespace v8 {
namespace preparser {
+typedef uint8_t byte;
+
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparse-data-format.h for the data format.
namespace i = v8::internal;
+class DuplicateFinder {
+ public:
+ explicit DuplicateFinder(i::UnicodeCache* constants)
+ : unicode_constants_(constants),
+ backing_store_(16),
+ map_(new i::HashMap(&Match)) { }
+
+ ~DuplicateFinder() {
+ delete map_;
+ }
+
+ int AddAsciiSymbol(i::Vector<const char> key, int value);
+ int AddUC16Symbol(i::Vector<const uint16_t> key, int value);
+ // Add a a number literal by converting it (if necessary)
+ // to the string that ToString(ToNumber(literal)) would generate.
+ // and then adding that string with AddAsciiSymbol.
+ // This string is the actual value used as key in an object literal,
+ // and the one that must be different from the other keys.
+ int AddNumber(i::Vector<const char> key, int value);
+
+ private:
+ int AddSymbol(i::Vector<const byte> key, bool is_ascii, int value);
+ // Backs up the key and its length in the backing store.
+ // The backup is stored with a base 127 encoding of the
+ // length (plus a bit saying whether the string is ASCII),
+ // followed by the bytes of the key.
+ byte* BackupKey(i::Vector<const byte> key, bool is_ascii);
+
+ // Compare two encoded keys (both pointing into the backing store)
+ // for having the same base-127 encoded lengths and ASCII-ness,
+ // and then having the same 'length' bytes following.
+ static bool Match(void* first, void* second);
+ // Creates a hash from a sequence of bytes.
+ static uint32_t Hash(i::Vector<const byte> key, bool is_ascii);
+ // Checks whether a string containing a JS number is its canonical
+ // form.
+ static bool IsNumberCanonical(i::Vector<const char> key);
+
+ // Size of buffer. Sufficient for using it to call DoubleToCString in
+ // from conversions.h.
+ static const int kBufferSize = 100;
+
+ i::UnicodeCache* unicode_constants_;
+ // Backing store used to store strings used as hashmap keys.
+ i::SequenceCollector<unsigned char> backing_store_;
+ i::HashMap* map_;
+ // Buffer used for string->number->canonical string conversions.
+ char number_buffer_[kBufferSize];
+};
+
+
class PreParser {
public:
enum PreParseResult {
}
private:
+ // Used to detect duplicates in object literals. Each of the values
+ // kGetterProperty, kSetterProperty and kValueProperty represents
+ // a type of object literal property. When parsing a property, its
+ // type value is stored in the DuplicateFinder for the property name.
+ // Values are chosen so that having intersection bits means the there is
+ // an incompatibility.
+ // I.e., you can add a getter to a property that already has a setter, since
+ // kGetterProperty and kSetterProperty doesn't intersect, but not if it
+ // already has a getter or a value. Adding the getter to an existing
+ // setter will store the value (kGetterProperty | kSetterProperty), which
+ // is incompatible with adding any further properties.
+ enum PropertyType {
+ kNone = 0,
+ // Bit patterns representing different object literal property types.
+ kGetterProperty = 1,
+ kSetterProperty = 2,
+ kValueProperty = 7,
+ // Helper constants.
+ kValueFlag = 4
+ };
+
+ // Checks the type of conflict based on values coming from PropertyType.
+ bool HasConflict(int type1, int type2) { return (type1 & type2) != 0; }
+ bool IsDataDataConflict(int type1, int type2) {
+ return ((type1 & type2) & kValueFlag) != 0;
+ }
+ bool IsDataAccessorConflict(int type1, int type2) {
+ return ((type1 ^ type2) & kValueFlag) != 0;
+ }
+ bool IsAccessorAccessorConflict(int type1, int type2) {
+ return ((type1 | type2) & kValueFlag) == 0;
+ }
+
+
+ void CheckDuplicate(DuplicateFinder* finder,
+ i::Token::Value property,
+ int type,
+ bool* ok);
+
// These types form an algebra over syntactic categories that is just
// rich enough to let us recognize and propagate the constructs that
// are either being counted in the preparser data, or is important
// Report syntax error
void ReportUnexpectedToken(i::Token::Value token);
+ void ReportMessageAt(i::Scanner::Location location,
+ const char* type,
+ const char* name_opt) {
+ log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
+ }
void ReportMessageAt(int start_pos,
int end_pos,
const char* type,
return next_.literal_chars->length();
}
+ UnicodeCache* unicode_cache() { return unicode_cache_; }
+
static const int kCharacterLookaheadBufferSize = 1;
protected:
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
+#include <math.h>
#include <limits>
-#ifndef V8_INFINITY
-#define V8_INFINITY std::numeric_limits<double>::infinity()
-#endif
-
+#include "globals.h"
#include "utils.h"
-
#include "strtod.h"
#include "bignum.h"
#include "cached-powers.h"
public:
explicit Collector(int initial_capacity = kMinCapacity)
: index_(0), size_(0) {
- if (initial_capacity < kMinCapacity) {
- initial_capacity = kMinCapacity;
- }
current_chunk_ = Vector<T>::New(initial_capacity);
}
// Creates a new current chunk, and stores the old chunk in the chunks_ list.
void Grow(int min_capacity) {
ASSERT(growth_factor > 1);
- int growth = current_chunk_.length() * (growth_factor - 1);
- if (growth > max_growth) {
- growth = max_growth;
- }
- int new_capacity = current_chunk_.length() + growth;
- if (new_capacity < min_capacity) {
- new_capacity = min_capacity + growth;
+ int new_capacity;
+ int current_length = current_chunk_.length();
+ if (current_length < kMinCapacity) {
+ // The collector started out as empty.
+ new_capacity = min_capacity * growth_factor;
+ if (new_capacity < kMinCapacity) new_capacity = kMinCapacity;
+ } else {
+ int growth = current_length * (growth_factor - 1);
+ if (growth > max_growth) {
+ growth = max_growth;
+ }
+ new_capacity = current_length + growth;
+ if (new_capacity < min_capacity) {
+ new_capacity = min_capacity + growth;
+ }
}
Vector<T> new_chunk = Vector<T>::New(new_capacity);
int new_index = PrepareGrow(new_chunk);
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please
+// refer to The Open Group Base Specification for specification of the correct
+// semantics for these functions.
+// (http://www.opengroup.org/onlinepubs/000095399/)
+#ifdef _MSC_VER
+
+#undef V8_WIN32_LEAN_AND_MEAN
+#define V8_WIN32_HEADERS_FULL
+#include "win32-headers.h"
+#include <limits.h> // Required for INT_MAX etc.
+#include <math.h>
+#include <float.h> // Required for DBL_MAX and on Win32 for finite()
+#include "win32-math.h"
+
+#include "checks.h"
+
+namespace v8 {
+
+// Test for finite value - usually defined in math.h
+int isfinite(double x) {
+ return _finite(x);
+}
+
+} // namespace v8
+
+
+// Test for a NaN (not a number) value - usually defined in math.h
+int isnan(double x) {
+ return _isnan(x);
+}
+
+
+// Test for infinity - usually defined in math.h
+int isinf(double x) {
+ return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0;
+}
+
+
+// Test if x is less than y and both nominal - usually defined in math.h
+int isless(double x, double y) {
+ return isnan(x) || isnan(y) ? 0 : x < y;
+}
+
+
+// Test if x is greater than y and both nominal - usually defined in math.h
+int isgreater(double x, double y) {
+ return isnan(x) || isnan(y) ? 0 : x > y;
+}
+
+
+// Classify floating point number - usually defined in math.h
+int fpclassify(double x) {
+ // Use the MS-specific _fpclass() for classification.
+ int flags = _fpclass(x);
+
+ // Determine class. We cannot use a switch statement because
+ // the _FPCLASS_ constants are defined as flags.
+ if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL;
+ if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO;
+ if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL;
+ if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE;
+
+ // All cases should be covered by the code above.
+ ASSERT(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN));
+ return FP_NAN;
+}
+
+
+// Test sign - usually defined in math.h
+int signbit(double x) {
+ // We need to take care of the special case of both positive
+ // and negative versions of zero.
+ if (x == 0)
+ return _fpclass(x) & _FPCLASS_NZ;
+ else
+ return x < 0;
+}
+
+#endif // _MSC_VER
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please
+// refer to The Open Group Base Specification for specification of the correct
+// semantics for these functions.
+// (http://www.opengroup.org/onlinepubs/000095399/)
+
+#ifndef V8_WIN32_MATH_H_
+#define V8_WIN32_MATH_H_
+
+#ifndef _MSC_VER
+#error Wrong environment, expected MSVC.
+#endif // _MSC_VER
+
+enum {
+ FP_NAN,
+ FP_INFINITE,
+ FP_ZERO,
+ FP_SUBNORMAL,
+ FP_NORMAL
+};
+
+namespace v8 {
+
+int isfinite(double x);
+
+} // namespace v8
+
+int isnan(double x);
+int isinf(double x);
+int isless(double x, double y);
+int isgreater(double x, double y);
+int fpclassify(double x);
+int signbit(double x);
+
+#endif // V8_WIN32_MATH_H_
--- /dev/null
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Templatated tests with duplicate parameter names.
+
+# ----------------------------------------------------------------------
+# Constants and utility functions
+
+# A template that performs the same strict-mode test in different
+# scopes (global scope, function scope, and nested function scope),
+# and in non-strict mode too.
+def DuplicateParameterTest(name, source):
+ expectation = "strict_param_dupe"
+ non_selfstrict = {"selfstrict":"", "id":"selfnormal"}
+
+ Template(name, '"use strict";\n' + source)(non_selfstrict, expectation)
+ Template(name + '-infunc',
+ 'function foo() {\n "use strict";\n' + source +'\n}\n')(
+ non_selfstrict, expectation)
+ Template(name + '-infunc2',
+ 'function foo() {\n "use strict";\n function bar() {\n' +
+ source +'\n }\n}\n')(non_selfstrict, expectation)
+
+ selfstrict = {"selfstrict": "\"use strict\";", "id": "selfstrict"}
+ nestedstrict = {"selfstrict": "function bar(){\"use strict\";}",
+ "id": "nestedstrict"}
+ selfstrictnestedclean = {"selfstrict": """
+ "use strict";
+ function bar(){}
+ """, "id": "selfstrictnestedclean"}
+ selftest = Template(name + '-$id', source)
+ selftest(selfstrict, expectation)
+ selftest(selfstrictnestedclean, expectation)
+ selftest(nestedstrict, None)
+ selftest(non_selfstrict, None)
+
+
+# ----------------------------------------------------------------------
+# Test templates
+
+DuplicateParameterTest("dups", """
+ function foo(a, a) { $selfstrict }
+""");
+
+DuplicateParameterTest("dups-apart", """
+ function foo(a, b, c, d, e, f, g, h, i, j, k, l, m, n, a) { $selfstrict }
+""");
+
+DuplicateParameterTest("dups-escaped", """
+ function foo(\u0061, b, c, d, e, f, g, h, i, j, k, l, m, n, a) { $selfstrict }
+""");
+
+DuplicateParameterTest("triples", """
+ function foo(a, b, c, d, e, f, g, h, a, i, j, k, l, m, n, a) { $selfstrict }
+""");
+
+DuplicateParameterTest("escapes", """
+ function foo(a, \u0061) { $selfstrict }
+""");
+
+DuplicateParameterTest("long-names", """
+ function foo(arglebargleglopglyfarglebargleglopglyfarglebargleglopglyfa,
+ arglebargleglopglyfarglebargleglopglyfarglebargleglopglyfa) {
+ $selfstrict
+ }
+""");
--- /dev/null
+# Copyright 2011 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Tests of duplicate properties in object literals.
+
+# ----------------------------------------------------------------------
+# Utility functions to generate a number of tests for each property
+# name pair.
+
+def PropertyTest(name, propa, propb, allow_strict = True):
+ replacement = {"id1": propa, "id2": propb, "name": name}
+
+ # Tests same test in both strict and non-strict context.
+ def StrictTest(name, source, replacement, expectation):
+ if (allow_strict):
+ Template("strict-" + name,
+ "\"use strict\";\n" + source)(replacement, expectation)
+ Template(name, source)(replacement, expectation)
+
+ # This one only fails in non-strict context.
+ if (allow_strict):
+ Template("strict-$name-data-data", """
+ "use strict";
+ var o = {$id1: 42, $id2: 42};
+ """)(replacement, "strict_duplicate_property")
+
+ Template("$name-data-data", """
+ var o = {$id1: 42, $id2: 42};
+ """)(replacement, None)
+
+ StrictTest("$name-data-get", """
+ var o = {$id1: 42, get $id2(){}};
+ """, replacement, "accessor_data_property")
+
+ StrictTest("$name-data-set", """
+ var o = {$id1: 42, set $id2(v){}};
+ """, replacement, "accessor_data_property")
+
+ StrictTest("$name-get-data", """
+ var o = {get $id1(){}, $id2: 42};
+ """, replacement, "accessor_data_property")
+
+ StrictTest("$name-set-data", """
+ var o = {set $id1(v){}, $id2: 42};
+ """, replacement, "accessor_data_property")
+
+ StrictTest("$name-get-get", """
+ var o = {get $id1(){}, get $id2(){}};
+ """, replacement, "accessor_get_set")
+
+ StrictTest("$name-set-set", """
+ var o = {set $id1(v){}, set $id2(v){}};
+ """, replacement, "accessor_get_set")
+
+ StrictTest("$name-nested-get", """
+ var o = {get $id1(){}, o: {get $id2(){} } };
+ """, replacement, None)
+
+ StrictTest("$name-nested-set", """
+ var o = {set $id1(){}, o: {set $id2(){} } };
+ """, replacement, None)
+
+
+def TestBothWays(name, propa, propb, allow_strict = True):
+ PropertyTest(name + "-1", propa, propb, allow_strict)
+ PropertyTest(name + "-2", propb, propa, allow_strict)
+
+def TestSame(name, prop, allow_strict = True):
+ PropertyTest(name, prop, prop, allow_strict)
+
+#-----------------------------------------------------------------------
+
+# Simple identifier property
+TestSame("a", "a")
+
+# Get/set identifiers
+TestSame("get-id", "get")
+TestSame("set-id", "set")
+
+# Number properties
+TestSame("0", "0")
+TestSame("0.1", "0.1")
+TestSame("1.0", "1.0")
+TestSame("42.33", "42.33")
+TestSame("2^32-2", "4294967294")
+TestSame("2^32", "4294967296")
+TestSame("2^53", "9007199254740992")
+TestSame("Hex20", "0x20")
+TestSame("exp10", "1e10")
+TestSame("exp20", "1e20")
+TestSame("Oct40", "040", False);
+
+
+# String properties
+TestSame("str-a", '"a"')
+TestSame("str-0", '"0"')
+TestSame("str-42", '"42"')
+TestSame("str-empty", '""')
+
+# Keywords
+TestSame("if", "if")
+TestSame("case", "case")
+
+# Future reserved keywords
+TestSame("public", "public")
+TestSame("class", "class")
+
+
+# Test that numbers are converted to string correctly.
+
+TestBothWays("hex-int", "0x20", "32")
+TestBothWays("oct-int", "040", "32", False) # Octals disallowed in strict mode.
+TestBothWays("dec-int", "32.00", "32")
+TestBothWays("dec-underflow-int",
+ "32.00000000000000000000000000000000000000001", "32")
+TestBothWays("exp-int", "3.2e1", "32")
+TestBothWays("exp-int", "3200e-2", "32")
+TestBothWays("overflow-inf", "1e2000", "Infinity")
+TestBothWays("overflow-inf-exact", "1.797693134862315808e+308", "Infinity")
+TestBothWays("non-overflow-inf-exact", "1.797693134862315807e+308",
+ "1.7976931348623157e+308")
+TestBothWays("underflow-0", "1e-2000", "0")
+TestBothWays("underflow-0-exact", "2.4703282292062E-324", "0")
+TestBothWays("non-underflow-0-exact", "2.4703282292063E-324", "5e-324")
+TestBothWays("precission-loss-high", "9007199254740992", "9007199254740993")
+TestBothWays("precission-loss-low", "1.9999999999999998", "1.9999999999999997")
+TestBothWays("non-canonical-literal-int", "1.0", "1")
+TestBothWays("non-canonical-literal-frac", "1.50", "1.5")
+TestBothWays("rounding-down", "1.12512512512512452", "1.1251251251251244")
+TestBothWays("rounding-up", "1.12512512512512453", "1.1251251251251246")
+
+TestBothWays("hex-int-str", "0x20", '"32"')
+TestBothWays("dec-int-str", "32.00", '"32"')
+TestBothWays("exp-int-str", "3.2e1", '"32"')
+TestBothWays("overflow-inf-str", "1e2000", '"Infinity"')
+TestBothWays("underflow-0-str", "1e-2000", '"0"')
+TestBothWays("non-canonical-literal-int-str", "1.0", '"1"')
+TestBothWays("non-canonical-literal-frac-str", "1.50", '"1.5"')
def ParsePythonTestTemplates(self, result, filename,
executable, current_path, mode):
pathname = join(self.root, filename + ".pyt")
- source = open(pathname).read();
def Test(name, source, expectation):
throws = None
if (expectation is not None):
testsource = testsource.replace("$"+key, replacement[key]);
Test(testname, testsource, expectation)
return MkTest
- eval(compile(source, pathname, "exec"),
- {"Test": Test, "Template": Template}, {})
+ execfile(pathname, {"Test": Test, "Template": Template})
def ListTests(self, current_path, path, mode, variant_flags):
executable = 'preparser'
filenames.sort()
for file in filenames:
# Each file as a python source file to be executed in a specially
- # perparsed environment (defining the Template and Test functions)
+ # created environment (defining the Template and Test functions)
self.ParsePythonTestTemplates(result, file,
executable, current_path, mode)
return result
'../../src/disasm.h',
'../../src/disassembler.cc',
'../../src/disassembler.h',
- '../../src/dtoa.cc',
- '../../src/dtoa.h',
'../../src/diy-fp.cc',
'../../src/diy-fp.h',
'../../src/double.h',
+ '../../src/dtoa.cc',
+ '../../src/dtoa.h',
'../../src/elements.cc',
'../../src/elements.h',
'../../src/execution.cc',
['OS=="win"', {
'sources': [
'../../src/platform-win32.cc',
+ '../../src/win32-math.cc',
+ '../../src/win32-math.h',
],
'msvs_disabled_warnings': [4351, 4355, 4800],
'link_settings': {
'../../src',
],
'sources': [
+ '../../include/v8-preparser.h',
+ '../../include/v8stdint.h',
'../../src/allocation.cc',
+ '../../src/allocation.h',
'../../src/bignum.cc',
+ '../../src/bignum.h',
+ '../../src/bignum-dtoa.cc',
+ '../../src/bignum-dtoa.h',
'../../src/cached-powers.cc',
+ '../../src/cached-powers.h',
+ '../../src/char-predicates-inl.h',
+ '../../src/char-predicates.h',
+ '../../src/checks.h',
+ '../../src/conversions-inl.h',
'../../src/conversions.cc',
+ '../../src/conversions.h',
+ '../../src/diy-fp.cc',
+ '../../src/diy-fp.h',
+ '../../src/double.h',
+ '../../src/dtoa.cc',
+ '../../src/dtoa.h',
+ '../../src/fast-dtoa.cc',
+ '../../src/fast-dtoa.h',
+ '../../src/fixed-dtoa.cc',
+ '../../src/fixed-dtoa.h',
+ '../../src/globals.h',
'../../src/hashmap.cc',
+ '../../src/hashmap.h',
+ '../../src/list-inl.h',
+ '../../src/list.h',
+ '../../src/preparse-data-format.h',
'../../src/preparse-data.cc',
+ '../../src/preparse-data.h',
'../../src/preparser.cc',
+ '../../src/preparser.h',
'../../src/preparser-api.cc',
'../../src/scanner-base.cc',
+ '../../src/scanner-base.h',
'../../src/strtod.cc',
+ '../../src/strtod.h',
'../../src/token.cc',
+ '../../src/token.h',
+ '../../src/unicode-inl.h',
'../../src/unicode.cc',
+ '../../src/unicode.h',
+ '../../src/utils-inl.h',
'../../src/utils.cc',
+ '../../src/utils.h',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'sources': [
+ '../../src/win32-math.cc',
+ '../../src/win32-math.h',
+ ]}],
],
},
],