Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: test/cctest/test-api.cc

Issue 366153002: Add script streaming API (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased again? Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/scanner-character-streams.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 23017 matching lines...) Expand 10 before | Expand all | Expand 10 after
23028 23028
23029 v8::Handle<Context> context = Context::New(isolate); 23029 v8::Handle<Context> context = Context::New(isolate);
23030 v8::Context::Scope context_scope(context); 23030 v8::Context::Scope context_scope(context);
23031 23031
23032 v8::Handle<v8::Object> obj = object_template->NewInstance(); 23032 v8::Handle<v8::Object> obj = object_template->NewInstance();
23033 obj->Set(v8_str("key"), v8_str("value")); 23033 obj->Set(v8_str("key"), v8_str("value"));
23034 obj->Delete(v8_str("key")); 23034 obj->Delete(v8_str("key"));
23035 23035
23036 obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2")); 23036 obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
23037 } 23037 }
23038
23039
23040 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23041 public:
23042 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23043
23044 virtual size_t GetMoreData(const uint8_t** src) {
23045 // Unlike in real use cases, this function will never block.
23046 if (chunks_[index_] == NULL) {
23047 return 0;
23048 }
23049 // Copy the data, since the caller takes ownership of it.
23050 size_t len = strlen(chunks_[index_]);
23051 // We don't need to zero-terminate since we return the length.
23052 uint8_t* copy = new uint8_t[len];
23053 memcpy(copy, chunks_[index_], len);
23054 *src = copy;
23055 ++index_;
23056 return len;
23057 }
23058
23059 // Helper for constructing a string from chunks (the compilation needs it
23060 // too).
23061 static char* FullSourceString(const char** chunks) {
23062 size_t total_len = 0;
23063 for (size_t i = 0; chunks[i] != NULL; ++i) {
23064 total_len += strlen(chunks[i]);
23065 }
23066 char* full_string = new char[total_len + 1];
23067 size_t offset = 0;
23068 for (size_t i = 0; chunks[i] != NULL; ++i) {
23069 size_t len = strlen(chunks[i]);
23070 memcpy(full_string + offset, chunks[i], len);
23071 offset += len;
23072 }
23073 full_string[total_len] = 0;
23074 return full_string;
23075 }
23076
23077 private:
23078 const char** chunks_;
23079 unsigned index_;
23080 };
23081
23082
23083 // Helper function for running streaming tests.
23084 void RunStreamingTest(const char** chunks,
23085 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23086 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23087 bool expected_success = true) {
23088 LocalContext env;
23089 v8::Isolate* isolate = env->GetIsolate();
23090 v8::HandleScope scope(isolate);
23091 v8::TryCatch try_catch;
23092
23093 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23094 encoding);
23095 v8::ScriptCompiler::ScriptStreamingTask* task =
23096 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23097
23098 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23099 // task here in the main thread.
23100 task->Run();
23101 delete task;
23102
23103 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23104 char* full_source = TestSourceStream::FullSourceString(chunks);
23105
23106 // The possible errors are only produced while compiling.
23107 CHECK_EQ(false, try_catch.HasCaught());
23108
23109 v8::Handle<Script> script = v8::ScriptCompiler::Compile(
23110 isolate, &source, v8_str(full_source), origin);
23111 if (expected_success) {
23112 CHECK(!script.IsEmpty());
23113 v8::Handle<Value> result(script->Run());
23114 // All scripts are supposed to return the fixed value 13 when ran.
23115 CHECK_EQ(13, result->Int32Value());
23116 } else {
23117 CHECK(script.IsEmpty());
23118 CHECK(try_catch.HasCaught());
23119 }
23120 delete[] full_source;
23121 }
23122
23123
23124 TEST(StreamingSimpleScript) {
23125 // This script is unrealistically small, since no one chunk is enough to fill
23126 // the backing buffer of Scanner, let alone overflow it.
23127 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23128 NULL};
23129 RunStreamingTest(chunks);
23130 }
23131
23132
23133 TEST(StreamingBiggerScript) {
23134 const char* chunk1 =
23135 "function foo() {\n"
23136 " // Make this chunk sufficiently long so that it will overflow the\n"
23137 " // backing buffer of the Scanner.\n"
23138 " var i = 0;\n"
23139 " var result = 0;\n"
23140 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23141 " result = 0;\n"
23142 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23143 " result = 0;\n"
23144 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23145 " result = 0;\n"
23146 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23147 " return result;\n"
23148 "}\n";
23149 const char* chunks[] = {chunk1, "foo(); ", NULL};
23150 RunStreamingTest(chunks);
23151 }
23152
23153
23154 TEST(StreamingScriptWithParseError) {
23155 // Test that parse errors from streamed scripts are propagated correctly.
23156 {
23157 char chunk1[] =
23158 " // This will result in a parse error.\n"
23159 " var if else then foo";
23160 char chunk2[] = " 13\n";
23161 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23162
23163 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23164 false);
23165 }
23166 // Test that the next script succeeds normally.
23167 {
23168 char chunk1[] =
23169 " // This will be parsed successfully.\n"
23170 " function foo() { return ";
23171 char chunk2[] = " 13; }\n";
23172 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23173
23174 RunStreamingTest(chunks);
23175 }
23176 }
23177
23178
23179 TEST(StreamingUtf8Script) {
23180 const char* chunk1 =
23181 "function foo() {\n"
23182 " // This function will contain an UTF-8 character which is not in\n"
23183 " // ASCII.\n"
23184 " var foob\uc481r = 13;\n"
23185 " return foob\uc481r;\n"
23186 "}\n";
23187 const char* chunks[] = {chunk1, "foo(); ", NULL};
23188 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23189 }
23190
23191
23192 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23193 // A sanity check to prove that the approach of splitting UTF-8
23194 // characters is correct. Here is an UTF-8 character which will take three
23195 // bytes.
23196 const char* reference = "\uc481";
23197 CHECK_EQ(3, strlen(reference));
23198 char chunk1[] =
23199 "function foo() {\n"
23200 " // This function will contain an UTF-8 character which is not in\n"
23201 " // ASCII.\n"
23202 " var foob";
23203 char chunk2[] =
23204 "XXXr = 13;\n"
23205 " return foob\uc481r;\n"
23206 "}\n";
23207 for (int i = 0; i < 3; ++i) {
23208 chunk2[i] = reference[i];
23209 }
23210 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23211 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23212 }
23213
23214
23215 TEST(StreamingUtf8ScriptWithSplitCharacters) {
23216 // Stream data where a multi-byte UTF-8 character is split between two data
23217 // chunks.
23218 const char* reference = "\uc481";
23219 char chunk1[] =
23220 "function foo() {\n"
23221 " // This function will contain an UTF-8 character which is not in\n"
23222 " // ASCII.\n"
23223 " var foobX";
23224 char chunk2[] =
23225 "XXr = 13;\n"
23226 " return foob\uc481r;\n"
23227 "}\n";
23228 chunk1[strlen(chunk1) - 1] = reference[0];
23229 chunk2[0] = reference[1];
23230 chunk2[1] = reference[2];
23231 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23232 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23233 }
23234
23235
23236 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23237 // Tests edge cases which should still be decoded correctly.
23238
23239 // Case 1: a chunk contains only bytes for a split character (and no other
23240 // data). This kind of a chunk would be exceptionally small, but we should
23241 // still decode it correctly.
23242 const char* reference = "\uc481";
23243 fprintf(stderr, "%d %d %d\n", reference[0], reference[1], reference[2]);
23244 // The small chunk is at the beginning of the split character
23245 {
23246 char chunk1[] =
23247 "function foo() {\n"
23248 " // This function will contain an UTF-8 character which is not in\n"
23249 " // ASCII.\n"
23250 " var foob";
23251 char chunk2[] = "XX";
23252 char chunk3[] =
23253 "Xr = 13;\n"
23254 " return foob\uc481r;\n"
23255 "}\n";
23256 chunk2[0] = reference[0];
23257 chunk2[1] = reference[1];
23258 chunk3[0] = reference[2];
23259 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23260 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23261 }
23262 // The small chunk is at the end of a character
23263 {
23264 char chunk1[] =
23265 "function foo() {\n"
23266 " // This function will contain an UTF-8 character which is not in\n"
23267 " // ASCII.\n"
23268 " var foobX";
23269 char chunk2[] = "XX";
23270 char chunk3[] =
23271 "r = 13;\n"
23272 " return foob\uc481r;\n"
23273 "}\n";
23274 chunk1[strlen(chunk1) - 1] = reference[0];
23275 chunk2[0] = reference[1];
23276 chunk2[1] = reference[2];
23277 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23278 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23279 }
23280 // Case 2: the script ends with a multi-byte character. Make sure that it's
23281 // decoded correctly and not just ignored.
23282 {
23283 char chunk1[] =
23284 "var foob\uc481 = 13;\n"
23285 "foob\uc481";
23286 const char* chunks[] = {chunk1, NULL};
23287 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23288 }
23289 }
23290
23291
23292 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23293 // Test cases where a UTF-8 character is split over several chunks. Those
23294 // cases are not supported (the embedder should give the data in big enough
23295 // chunks), but we shouldn't crash, just produce a parse error.
23296 const char* reference = "\uc481";
23297 char chunk1[] =
23298 "function foo() {\n"
23299 " // This function will contain an UTF-8 character which is not in\n"
23300 " // ASCII.\n"
23301 " var foobX";
23302 char chunk2[] = "X";
23303 char chunk3[] =
23304 "Xr = 13;\n"
23305 " return foob\uc481r;\n"
23306 "}\n";
23307 chunk1[strlen(chunk1) - 1] = reference[0];
23308 chunk2[0] = reference[1];
23309 chunk3[0] = reference[2];
23310 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23311
23312 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23313 }
23314
23315
23316 TEST(StreamingProducesParserCache) {
23317 i::FLAG_min_preparse_length = 0;
23318 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23319 NULL};
23320
23321 LocalContext env;
23322 v8::Isolate* isolate = env->GetIsolate();
23323 v8::HandleScope scope(isolate);
23324
23325 v8::ScriptCompiler::StreamedSource source(
23326 new TestSourceStream(chunks),
23327 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23328 v8::ScriptCompiler::ScriptStreamingTask* task =
23329 v8::ScriptCompiler::StartStreamingScript(
23330 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23331
23332 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23333 // task here in the main thread.
23334 task->Run();
23335 delete task;
23336
23337 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23338 CHECK(cached_data != NULL);
23339 CHECK(cached_data->data != NULL);
23340 CHECK_GT(cached_data->length, 0);
23341 }
OLDNEW
« no previous file with comments | « src/scanner-character-streams.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698