Remove asserts that do not hold when lazily compiling extension code.
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 31 Aug 2009 15:02:54 +0000 (15:02 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 31 Aug 2009 15:02:54 +0000 (15:02 +0000)
Add checks for the use of eval and with in natives files to the js2c
script.

Review URL: http://codereview.chromium.org/175009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2786 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/d8.js
src/parser.cc
test/cctest/test-api.cc
tools/js2c.py

index 2d52170..7249eca 100644 (file)
--- a/src/d8.js
+++ b/src/d8.js
@@ -1143,7 +1143,7 @@ function DebugResponseDetails(response) {
  * @constructor
  */
 function ProtocolPackage(json) {
-  this.packet_ = eval('(' + json + ')');
+  this.packet_ = JSON.parse(json);
   this.refs_ = [];
   if (this.packet_.refs) {
     for (var i = 0; i < this.packet_.refs.length; i++) {
index 5cc6341..0abb9ed 100644 (file)
@@ -2397,12 +2397,6 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
   // WithStatement ::
   //   'with' '(' Expression ')' Statement
 
-  // We do not allow the use of 'with' statements in the internal JS
-  // code. If 'with' statements were allowed, the simplified setup of
-  // the runtime context chain would allow access to properties in the
-  // global object from within a 'with' statement.
-  ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
-
   Expect(Token::WITH, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
   Expression* expr = ParseExpression(true, CHECK_OK);
@@ -3088,9 +3082,6 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
             Handle<String> name = callee->name();
             Variable* var = top_scope_->Lookup(name);
             if (var == NULL) {
-              // We do not allow direct calls to 'eval' in our internal
-              // JS files. Use builtin functions instead.
-              ASSERT(extension_ != NULL || !Bootstrapper::IsActive());
               top_scope_->RecordEvalCall();
               is_potentially_direct_eval = true;
             }
index d192ebb..80f91d3 100644 (file)
@@ -2673,40 +2673,67 @@ THREADED_TEST(SimpleExtensions) {
 }
 
 
-static const char* kEvalExtensionSource =
-  "function UseEval() {"
+static const char* kEvalExtensionSource1 =
+  "function UseEval1() {"
   "  var x = 42;"
   "  return eval('x');"
   "}";
 
 
+static const char* kEvalExtensionSource2 =
+  "(function() {"
+  "  var x = 42;"
+  "  function e() {"
+  "    return eval('x');"
+  "  }"
+  "  this.UseEval2 = e;"
+  "})()";
+
+
 THREADED_TEST(UseEvalFromExtension) {
   v8::HandleScope handle_scope;
-  v8::RegisterExtension(new Extension("evaltest", kEvalExtensionSource));
-  const char* extension_names[] = { "evaltest" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
+  v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
+  const char* extension_names[] = { "evaltest1", "evaltest2" };
+  v8::ExtensionConfiguration extensions(2, extension_names);
   v8::Handle<Context> context = Context::New(&extensions);
   Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("UseEval()"))->Run();
+  v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(42));
+  result = Script::Compile(v8_str("UseEval2()"))->Run();
   CHECK_EQ(result, v8::Integer::New(42));
 }
 
 
-static const char* kWithExtensionSource =
-  "function UseWith() {"
+static const char* kWithExtensionSource1 =
+  "function UseWith1() {"
   "  var x = 42;"
   "  with({x:87}) { return x; }"
   "}";
 
 
+
+static const char* kWithExtensionSource2 =
+  "(function() {"
+  "  var x = 42;"
+  "  function e() {"
+  "    with ({x:87}) { return x; }"
+  "  }"
+  "  this.UseWith2 = e;"
+  "})()";
+
+
 THREADED_TEST(UseWithFromExtension) {
   v8::HandleScope handle_scope;
-  v8::RegisterExtension(new Extension("withtest", kWithExtensionSource));
-  const char* extension_names[] = { "withtest" };
-  v8::ExtensionConfiguration extensions(1, extension_names);
+  v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
+  v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
+  const char* extension_names[] = { "withtest1", "withtest2" };
+  v8::ExtensionConfiguration extensions(2, extension_names);
   v8::Handle<Context> context = Context::New(&extensions);
   Context::Scope lock(context);
-  v8::Handle<Value> result = Script::Compile(v8_str("UseWith()"))->Run();
+  v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
+  CHECK_EQ(result, v8::Integer::New(87));
+  result = Script::Compile(v8_str("UseWith2()"))->Run();
   CHECK_EQ(result, v8::Integer::New(87));
 }
 
index 52fe35c..cae39e8 100755 (executable)
@@ -45,6 +45,13 @@ def ToCArray(lines):
   return ", ".join(result)
 
 
+def RemoveCommentsAndTrailingWhitespace(lines):
+  lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments
+  lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
+  lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace
+  return lines
+
+
 def CompressScript(lines, do_jsmin):
   # If we're not expecting this code to be user visible, we can run it through
   # a more aggressive minifier.
@@ -55,9 +62,7 @@ def CompressScript(lines, do_jsmin):
   # people print the source code using Function.prototype.toString().
   # Note that we could easily compress the scripts mode but don't
   # since we want it to remain readable.
-  lines = re.sub('//.*\n', '\n', lines) # end-of-line comments
-  lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments.
-  lines = re.sub('\s+\n+', '\n', lines) # trailing whitespace
+  lines = RemoveCommentsAndTrailingWhitespace(lines)
   return lines
 
 
@@ -96,6 +101,22 @@ def ParseValue(string):
     return string
 
 
+EVAL_PATTERN = re.compile(r'\beval\s*\(');
+WITH_PATTERN = re.compile(r'\bwith\s*\(');
+
+
+def Validate(lines, file):
+  lines = RemoveCommentsAndTrailingWhitespace(lines)
+  # Because of simplified context setup, eval and with is not
+  # allowed in the natives files.
+  eval_match = EVAL_PATTERN.search(lines)
+  if eval_match:
+    raise ("Eval disallowed in natives: %s" % file)
+  with_match = WITH_PATTERN.search(lines)
+  if with_match:
+    raise ("With statements disallowed in natives: %s" % file)
+
+
 def ExpandConstants(lines, constants):
   for key, value in constants.items():
     lines = lines.replace(key, str(value))
@@ -155,9 +176,9 @@ class PythonMacro:
       args.append(mapping[arg])
     return str(self.fun(*args))
 
-CONST_PATTERN = re.compile('^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
-MACRO_PATTERN = re.compile('^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
-PYTHON_MACRO_PATTERN = re.compile('^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
+CONST_PATTERN = re.compile(r'^const\s+([a-zA-Z0-9_]+)\s*=\s*([^;]*);$')
+MACRO_PATTERN = re.compile(r'^macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
+PYTHON_MACRO_PATTERN = re.compile(r'^python\s+macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*=\s*([^;]*);$')
 
 def ReadMacros(lines):
   constants = { }
@@ -275,15 +296,17 @@ def JS2C(source, target, env):
   # Build source code lines
   source_lines = [ ]
   source_lines_empty = []
-  for s in modules:
-    delay = str(s).endswith('-delay.js')
-    lines = ReadFile(str(s))
+  for module in modules:
+    filename = str(module)
+    delay = filename.endswith('-delay.js')
+    lines = ReadFile(filename)
     do_jsmin = lines.find('// jsminify this file, js2c: jsmin') != -1
     lines = ExpandConstants(lines, consts)
     lines = ExpandMacros(lines, macros)
+    Validate(lines, filename)
     lines = CompressScript(lines, do_jsmin)
     data = ToCArray(lines)
-    id = (os.path.split(str(s))[1])[:-3]
+    id = (os.path.split(filename)[1])[:-3]
     if delay: id = id[:-6]
     if delay:
       delay_ids.append((id, len(lines)))
@@ -291,7 +314,7 @@ def JS2C(source, target, env):
       ids.append((id, len(lines)))
     source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data })
     source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': 0 })
-  
+
   # Build delay support functions
   get_index_cases = [ ]
   get_script_source_cases = [ ]