Implement fromEnvironment on bool, int and String
This implements const constructor fromEnvironment on bool, int and String. The VM have the added -Dname=value option to define the value for the properties. All values are provided by using the -D - nothing is read from the environment. If the resulting value is null or - in the case of int.fromEnvironment - not a number an ArgumentError is thrown. This CL does not have any implementation for dart2js. This is a continuation of the change https://chromiumcodereview.appspot.com/24975002 by iposva@ BUG= R=iposva@google.com Review URL: https://codereview.chromium.org//50983002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@29642 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "bin/process.h"
|
||||
#include "bin/vmservice_impl.h"
|
||||
#include "platform/globals.h"
|
||||
#include "platform/hashmap.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
@@ -72,6 +73,8 @@ static bool start_vm_service = false;
|
||||
static int vm_service_server_port = -1;
|
||||
static const int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
|
||||
|
||||
// The environment provided through the command line using -D options.
|
||||
static dart::HashMap* environment = NULL;
|
||||
|
||||
static bool IsValidFlag(const char* name,
|
||||
const char* prefix,
|
||||
@@ -132,6 +135,48 @@ static bool ProcessPackageRootOption(const char* arg) {
|
||||
}
|
||||
|
||||
|
||||
static void* GetHashmapKeyFromString(char* key) {
|
||||
return reinterpret_cast<void*>(key);
|
||||
}
|
||||
|
||||
static bool ProcessEnvironmentOption(const char* arg) {
|
||||
ASSERT(arg != NULL);
|
||||
if (*arg == '\0') {
|
||||
// Ignore empty -D option.
|
||||
Log::PrintErr("No arguments given to -D option\n");
|
||||
return true;
|
||||
}
|
||||
if (environment == NULL) {
|
||||
environment = new HashMap(&HashMap::SameStringValue, 4);
|
||||
}
|
||||
// Split the name=value part of the -Dname=value argument.
|
||||
char* name;
|
||||
char* value = NULL;
|
||||
const char* equals_pos = strchr(arg, '=');
|
||||
if (equals_pos == NULL) {
|
||||
// No equal sign (name without value) currently not supported.
|
||||
Log::PrintErr("No value given to -D option\n");
|
||||
return false;
|
||||
} else {
|
||||
int name_len = equals_pos - arg;
|
||||
if (name_len == 0) {
|
||||
Log::PrintErr("No name given to -D option\n");
|
||||
return false;
|
||||
}
|
||||
// Split name=value into name and value.
|
||||
name = reinterpret_cast<char*>(malloc(name_len + 1));
|
||||
strncpy(name, arg, name_len);
|
||||
name[name_len] = '\0';
|
||||
value = strdup(equals_pos + 1);
|
||||
}
|
||||
HashMap::Entry* entry = environment->Lookup(
|
||||
GetHashmapKeyFromString(name), HashMap::StringHash(name), true);
|
||||
ASSERT(entry != NULL); // Lookup adds an entry if key not found.
|
||||
entry->value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool ProcessCompileAllOption(const char* arg) {
|
||||
ASSERT(arg != NULL);
|
||||
if (*arg != '\0') {
|
||||
@@ -246,6 +291,7 @@ static struct {
|
||||
{ "--verbose", ProcessVerboseOption },
|
||||
{ "-v", ProcessVerboseOption },
|
||||
{ "--package-root=", ProcessPackageRootOption },
|
||||
{ "-D", ProcessEnvironmentOption },
|
||||
// VM specific options to the standalone dart program.
|
||||
{ "--break-at=", ProcessBreakpointOption },
|
||||
{ "--compile_all", ProcessCompileAllOption },
|
||||
@@ -402,6 +448,38 @@ static Dart_Handle CreateRuntimeOptions(CommandLineOptions* options) {
|
||||
} \
|
||||
|
||||
|
||||
static Dart_Handle EnvironmentCallback(Dart_Handle name) {
|
||||
uint8_t* utf8_array;
|
||||
intptr_t utf8_len;
|
||||
Dart_Handle result = Dart_Null();
|
||||
Dart_Handle handle = Dart_StringToUTF8(name, &utf8_array, &utf8_len);
|
||||
if (Dart_IsError(handle)) {
|
||||
handle = Dart_ThrowException(
|
||||
DartUtils::NewDartArgumentError(Dart_GetError(handle)));
|
||||
} else {
|
||||
char* name_chars = reinterpret_cast<char*>(malloc(utf8_len + 1));
|
||||
memmove(name_chars, utf8_array, utf8_len);
|
||||
name_chars[utf8_len] = '\0';
|
||||
const char* value = NULL;
|
||||
if (environment != NULL) {
|
||||
HashMap::Entry* entry = environment->Lookup(
|
||||
GetHashmapKeyFromString(name_chars),
|
||||
HashMap::StringHash(name_chars),
|
||||
false);
|
||||
if (entry != NULL) {
|
||||
value = reinterpret_cast<char*>(entry->value);
|
||||
}
|
||||
}
|
||||
if (value != NULL) {
|
||||
result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(value),
|
||||
strlen(value));
|
||||
}
|
||||
free(name_chars);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Returns true on success, false on failure.
|
||||
static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri,
|
||||
const char* main,
|
||||
@@ -426,6 +504,9 @@ static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri,
|
||||
Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
result = Dart_SetEnvironmentCallback(EnvironmentCallback);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
// Load the specified application script into the newly created isolate.
|
||||
|
||||
// Prepare builtin and its dependent libraries for use to resolve URIs.
|
||||
@@ -906,6 +987,17 @@ int main(int argc, char** argv) {
|
||||
for (int i = 0; i < argc; i++) free(argv[i]);
|
||||
}
|
||||
|
||||
// Free environment if any.
|
||||
if (environment != NULL) {
|
||||
for (HashMap::Entry* p = environment->Start();
|
||||
p != NULL;
|
||||
p = environment->Next(p)) {
|
||||
free(p->key);
|
||||
free(p->value);
|
||||
}
|
||||
free(environment);
|
||||
}
|
||||
|
||||
return Process::GlobalExitCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -1477,7 +1477,7 @@ DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
|
||||
/**
|
||||
* Gets the data corresponding to the string object. This function returns
|
||||
* the data only for Latin-1 (ISO-8859-1) string objects. For all other
|
||||
* string objects it return and error.
|
||||
* string objects it returns an error.
|
||||
*
|
||||
* \param str A string.
|
||||
* \param latin1_array An array allocated by the caller, used to return
|
||||
@@ -2106,6 +2106,32 @@ typedef Dart_NativeFunction (*Dart_NativeEntryResolver)(Dart_Handle name,
|
||||
/* TODO(turnidge): Consider renaming to NativeFunctionResolver or
|
||||
* NativeResolver. */
|
||||
|
||||
/*
|
||||
* ===========
|
||||
* Environment
|
||||
* ===========
|
||||
*/
|
||||
|
||||
/**
|
||||
* An environment lookup callback function.
|
||||
*
|
||||
* \param name The name of the value to lookup in the environment.
|
||||
*
|
||||
* \return A valid handle to a string if the name exists in the
|
||||
* current environment or Dart_Null() if not.
|
||||
*/
|
||||
typedef Dart_Handle (*Dart_EnvironmentCallback)(Dart_Handle name);
|
||||
|
||||
/**
|
||||
* Sets the environment callback for the current isolate. This
|
||||
* callback is used to lookup environment values by name in the
|
||||
* current environment. This enables the embedder to supply values for
|
||||
* the const constructors bool.fromEnvironment, int.fromEnvironment
|
||||
* and String.fromEnvironment.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_SetEnvironmentCallback(
|
||||
Dart_EnvironmentCallback callback);
|
||||
|
||||
/**
|
||||
* Sets the callback used to resolve native functions for a library.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "vm/bootstrap_natives.h"
|
||||
|
||||
#include "include/dart_api.h"
|
||||
#include "vm/bigint_operations.h"
|
||||
#include "vm/dart_entry.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/exceptions.h"
|
||||
#include "vm/isolate.h"
|
||||
#include "vm/native_entry.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/object_store.h"
|
||||
#include "vm/symbols.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 3) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
|
||||
GET_NATIVE_ARGUMENT(Bool, default_value, arguments->NativeArgAt(2));
|
||||
// Call the embedder to supply us with the environment.
|
||||
Dart_EnvironmentCallback callback = isolate->environment_callback();
|
||||
if (callback != NULL) {
|
||||
Dart_Handle result = callback(Api::NewHandle(isolate, name.raw()));
|
||||
if (Dart_IsError(result)) {
|
||||
const Object& error =
|
||||
Object::Handle(isolate, Api::UnwrapHandle(result));
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(
|
||||
String::New(Error::Cast(error).ToErrorCString())));
|
||||
} else if (Dart_IsString(result)) {
|
||||
const char *chars;
|
||||
Dart_StringToCString(result, &chars);
|
||||
return (strcmp("true", chars) == 0)
|
||||
? Bool::True().raw() : Bool::False().raw();
|
||||
} else if (!Dart_IsNull(result)) {
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(String::New("Illegal environment value")));
|
||||
}
|
||||
}
|
||||
return default_value.raw();
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
patch class bool {
|
||||
|
||||
/* patch */ const factory bool.fromEnvironment(String name,
|
||||
{bool defaultValue})
|
||||
native "Bool_fromEnvironment";
|
||||
|
||||
int get _identityHashCode {
|
||||
return this ? 1231 : 1237;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
'sources': [
|
||||
'core_patch.dart',
|
||||
# The above file needs to be first as it imports required libraries.
|
||||
'bool.cc',
|
||||
'bool_patch.dart',
|
||||
'date.cc',
|
||||
'date_patch.dart',
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include "vm/bootstrap_natives.h"
|
||||
|
||||
#include "include/dart_api.h"
|
||||
#include "vm/bigint_operations.h"
|
||||
#include "vm/dart_entry.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/exceptions.h"
|
||||
#include "vm/isolate.h"
|
||||
#include "vm/native_entry.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/object_store.h"
|
||||
@@ -226,6 +229,61 @@ DEFINE_NATIVE_ENTRY(Integer_parse, 1) {
|
||||
}
|
||||
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Integer_fromEnvironment, 3) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
|
||||
GET_NATIVE_ARGUMENT(Integer, default_value, arguments->NativeArgAt(2));
|
||||
// Call the embedder to supply us with the environment.
|
||||
Dart_EnvironmentCallback callback = isolate->environment_callback();
|
||||
if (callback != NULL) {
|
||||
Dart_Handle result = callback(Api::NewHandle(isolate, name.raw()));
|
||||
if (Dart_IsError(result)) {
|
||||
const Object& error =
|
||||
Object::Handle(isolate, Api::UnwrapHandle(result));
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(
|
||||
String::New(Error::Cast(error).ToErrorCString())));
|
||||
} else if (Dart_IsString(result)) {
|
||||
uint8_t* digits;
|
||||
intptr_t digits_len;
|
||||
Dart_StringToUTF8(result, &digits, &digits_len);
|
||||
if (digits_len > 0) {
|
||||
// Check for valid integer literal before constructing integer object.
|
||||
// Skip leading minus if present.
|
||||
if (digits[0] == '-') {
|
||||
digits++;
|
||||
digits_len--;
|
||||
}
|
||||
// Check remaining string for decimal or hex-decimal literal.
|
||||
bool is_number = true;
|
||||
if (digits_len > 2 &&
|
||||
digits[0] == '0' &&
|
||||
(digits[1] == 'x' || digits[1] == 'X')) {
|
||||
for (int i = 2; i < digits_len && is_number; i++) {
|
||||
is_number = ('0' <= digits[i] && digits[i] <= '9') ||
|
||||
('A' <= digits[i] && digits[i] <= 'F') ||
|
||||
('a' <= digits[i] && digits[i] <= 'f');
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < digits_len && is_number; i++) {
|
||||
is_number = '0' <= digits[i] && digits[i] <= '9';
|
||||
}
|
||||
}
|
||||
if (digits_len > 0 && is_number) {
|
||||
const Object& value =
|
||||
Object::Handle(isolate, Api::UnwrapHandle(result));
|
||||
ASSERT(value.IsString());
|
||||
return Integer::NewCanonical(String::Cast(value));
|
||||
}
|
||||
}
|
||||
} else if (!Dart_IsNull(result)) {
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(String::New("Illegal environment value")));
|
||||
}
|
||||
}
|
||||
return default_value.raw();
|
||||
}
|
||||
|
||||
|
||||
// Passing true for 'silent' prevents throwing JavascriptIntegerOverflow.
|
||||
static RawInteger* ShiftOperationHelper(Token::Kind kind,
|
||||
const Integer& value,
|
||||
|
||||
@@ -87,6 +87,10 @@ patch class int {
|
||||
return _slowParse(source, radix, onError);
|
||||
}
|
||||
|
||||
/* patch */ const factory int.fromEnvironment(String name,
|
||||
{int defaultValue})
|
||||
native "Integer_fromEnvironment";
|
||||
|
||||
static int _slowParse(String source, int radix, int onError(String str)) {
|
||||
if (source is! String) throw new ArgumentError(source);
|
||||
if (radix is! int) throw new ArgumentError("Radix is not an integer");
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
#include "vm/bootstrap_natives.h"
|
||||
|
||||
#include "include/dart_api.h"
|
||||
#include "vm/exceptions.h"
|
||||
#include "vm/dart_api_impl.h"
|
||||
#include "vm/isolate.h"
|
||||
#include "vm/native_entry.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/symbols.h"
|
||||
@@ -12,6 +15,32 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_NATIVE_ENTRY(String_fromEnvironment, 3) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
|
||||
GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2));
|
||||
// Call the embedder to supply us with the environment.
|
||||
Dart_EnvironmentCallback callback = isolate->environment_callback();
|
||||
if (callback != NULL) {
|
||||
Dart_Handle result = callback(Api::NewHandle(isolate, name.raw()));
|
||||
if (Dart_IsError(result)) {
|
||||
const Object& error =
|
||||
Object::Handle(isolate, Api::UnwrapHandle(result));
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(
|
||||
String::New(Error::Cast(error).ToErrorCString())));
|
||||
} else if (Dart_IsString(result)) {
|
||||
const Object& value =
|
||||
Object::Handle(isolate, Api::UnwrapHandle(result));
|
||||
return Symbols::New(String::Cast(value));
|
||||
} else if (!Dart_IsNull(result)) {
|
||||
Exceptions::ThrowArgumentError(
|
||||
String::Handle(String::New("Illegal environment value")));
|
||||
}
|
||||
}
|
||||
return default_value.raw();
|
||||
}
|
||||
|
||||
|
||||
DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Instance, list, arguments->NativeArgAt(0));
|
||||
if (!list.IsGrowableObjectArray() && !list.IsArray()) {
|
||||
|
||||
@@ -6,6 +6,10 @@ patch class String {
|
||||
/* patch */ factory String.fromCharCodes(Iterable<int> charCodes) {
|
||||
return _StringBase.createFromCharCodes(charCodes);
|
||||
}
|
||||
|
||||
/* patch */ const factory String.fromEnvironment(String name,
|
||||
{String defaultValue})
|
||||
native "String_fromEnvironment";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,27 @@ class HashMap {
|
||||
return key1 == key2;
|
||||
}
|
||||
|
||||
static uint32_t StringHash(char* key) {
|
||||
uint32_t hash_ = 0;
|
||||
if (key == NULL) return hash_;
|
||||
int len = strlen(key);
|
||||
for (int i = 0; i < len; i++) {
|
||||
hash_ += key[i];
|
||||
hash_ += hash_ << 10;
|
||||
hash_ ^= hash_ >> 6;
|
||||
}
|
||||
hash_ += hash_ << 3;
|
||||
hash_ ^= hash_ >> 11;
|
||||
hash_ += hash_ << 15;
|
||||
return hash_ == 0 ? 1 : hash_;
|
||||
}
|
||||
|
||||
static bool SameStringValue(void* key1, void* key2) {
|
||||
return strcmp(reinterpret_cast<char*>(key1),
|
||||
reinterpret_cast<char*>(key2)) == 0;
|
||||
}
|
||||
|
||||
|
||||
// initial_capacity is the size of the initial hash map;
|
||||
// it must be a power of 2 (and thus must not be 0).
|
||||
HashMap(MatchFun match, uint32_t initial_capacity);
|
||||
|
||||
@@ -37,8 +37,10 @@ namespace dart {
|
||||
V(Integer_moduloFromInteger, 2) \
|
||||
V(Integer_greaterThanFromInteger, 2) \
|
||||
V(Integer_equalToInteger, 2) \
|
||||
V(Integer_fromEnvironment, 3) \
|
||||
V(Integer_parse, 1) \
|
||||
V(Integer_leftShiftWithMask32, 3) \
|
||||
V(Bool_fromEnvironment, 3) \
|
||||
V(RawReceivePortImpl_factory, 1) \
|
||||
V(RawReceivePortImpl_closeInternal, 1) \
|
||||
V(SendPortImpl_sendInternal_, 3) \
|
||||
@@ -100,6 +102,7 @@ namespace dart {
|
||||
V(String_charAt, 2) \
|
||||
V(String_codeUnitAt, 2) \
|
||||
V(String_concat, 2) \
|
||||
V(String_fromEnvironment, 3) \
|
||||
V(String_toLowerCase, 1) \
|
||||
V(String_toUpperCase, 1) \
|
||||
V(String_concatRange, 3) \
|
||||
|
||||
@@ -3910,6 +3910,17 @@ DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args,
|
||||
}
|
||||
|
||||
|
||||
// --- Environment ---
|
||||
DART_EXPORT Dart_Handle Dart_SetEnvironmentCallback(
|
||||
Dart_EnvironmentCallback callback) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
CHECK_ISOLATE(isolate);
|
||||
isolate->set_environment_callback(callback);
|
||||
return Api::Success();
|
||||
}
|
||||
|
||||
|
||||
// --- Scripts and Libraries ---
|
||||
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
|
||||
bool retval) {
|
||||
TRACE_API_CALL(CURRENT_FUNC);
|
||||
|
||||
@@ -284,6 +284,7 @@ Isolate::Isolate()
|
||||
top_context_(Context::null()),
|
||||
top_exit_frame_info_(0),
|
||||
init_callback_data_(NULL),
|
||||
environment_callback_(NULL),
|
||||
library_tag_handler_(NULL),
|
||||
api_state_(NULL),
|
||||
stub_code_(NULL),
|
||||
|
||||
@@ -174,6 +174,13 @@ class Isolate : public BaseIsolate {
|
||||
return init_callback_data_;
|
||||
}
|
||||
|
||||
Dart_EnvironmentCallback environment_callback() const {
|
||||
return environment_callback_;
|
||||
}
|
||||
void set_environment_callback(Dart_EnvironmentCallback value) {
|
||||
environment_callback_ = value;
|
||||
}
|
||||
|
||||
Dart_LibraryTagHandler library_tag_handler() const {
|
||||
return library_tag_handler_;
|
||||
}
|
||||
@@ -393,6 +400,7 @@ class Isolate : public BaseIsolate {
|
||||
RawContext* top_context_;
|
||||
uword top_exit_frame_info_;
|
||||
void* init_callback_data_;
|
||||
Dart_EnvironmentCallback environment_callback_;
|
||||
Dart_LibraryTagHandler library_tag_handler_;
|
||||
ApiState* api_state_;
|
||||
StubCode* stub_code_;
|
||||
|
||||
+33
-15
@@ -3104,9 +3104,13 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
|
||||
ErrorMsg(method->name_pos,
|
||||
"external method '%s' may not have a function body",
|
||||
method->name->ToCString());
|
||||
} else if (method->IsFactoryOrConstructor() && method->has_const) {
|
||||
} else if (method->IsConstructor() && method->has_const) {
|
||||
ErrorMsg(method->name_pos,
|
||||
"const constructor or factory '%s' may not have a function body",
|
||||
"const constructor '%s' may not have a function body",
|
||||
method->name->ToCString());
|
||||
} else if (method->IsFactory() && method->has_const) {
|
||||
ErrorMsg(method->name_pos,
|
||||
"const factory '%s' may not have a function body",
|
||||
method->name->ToCString());
|
||||
}
|
||||
if (method->redirect_name != NULL) {
|
||||
@@ -3128,9 +3132,9 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
|
||||
ErrorMsg(method->name_pos,
|
||||
"abstract method '%s' may not have a function body",
|
||||
method->name->ToCString());
|
||||
} else if (method->IsFactoryOrConstructor() && method->has_const) {
|
||||
} else if (method->IsConstructor() && method->has_const) {
|
||||
ErrorMsg(method->name_pos,
|
||||
"const constructor or factory '%s' may not be native",
|
||||
"const constructor '%s' may not be native",
|
||||
method->name->ToCString());
|
||||
}
|
||||
if (method->redirect_name != NULL) {
|
||||
@@ -8706,21 +8710,28 @@ RawObject* Parser::EvaluateConstConstructorCall(
|
||||
const AbstractTypeArguments& type_arguments,
|
||||
const Function& constructor,
|
||||
ArgumentListNode* arguments) {
|
||||
const int kNumExtraArgs = 2; // implicit rcvr and construction phase args.
|
||||
// Factories have one extra argument: the type arguments.
|
||||
// Constructors have 2 extra arguments: rcvr and construction phase.
|
||||
const int kNumExtraArgs = constructor.IsFactory() ? 1 : 2;
|
||||
const int num_arguments = arguments->length() + kNumExtraArgs;
|
||||
const Array& arg_values = Array::Handle(Array::New(num_arguments));
|
||||
Instance& instance = Instance::Handle();
|
||||
ASSERT(!constructor.IsFactory());
|
||||
instance = Instance::New(type_class, Heap::kOld);
|
||||
if (!type_arguments.IsNull()) {
|
||||
if (!type_arguments.IsInstantiated()) {
|
||||
ErrorMsg("type must be constant in const constructor");
|
||||
if (!constructor.IsFactory()) {
|
||||
instance = Instance::New(type_class, Heap::kOld);
|
||||
if (!type_arguments.IsNull()) {
|
||||
if (!type_arguments.IsInstantiated()) {
|
||||
ErrorMsg("type must be constant in const constructor");
|
||||
}
|
||||
instance.SetTypeArguments(
|
||||
AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
|
||||
}
|
||||
instance.SetTypeArguments(
|
||||
AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
|
||||
arg_values.SetAt(0, instance);
|
||||
arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
|
||||
} else {
|
||||
// Prepend type_arguments to list of arguments to factory.
|
||||
ASSERT(type_arguments.IsZoneHandle());
|
||||
arg_values.SetAt(0, type_arguments);
|
||||
}
|
||||
arg_values.SetAt(0, instance);
|
||||
arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
|
||||
for (int i = 0; i < arguments->length(); i++) {
|
||||
AstNode* arg = arguments->NodeAt(i);
|
||||
// Arguments have been evaluated to a literal value already.
|
||||
@@ -8747,6 +8758,10 @@ RawObject* Parser::EvaluateConstConstructorCall(
|
||||
return Object::null();
|
||||
}
|
||||
} else {
|
||||
if (constructor.IsFactory()) {
|
||||
// The factory method returns the allocated object.
|
||||
instance ^= result.raw();
|
||||
}
|
||||
return TryCanonicalize(instance, TokenPos());
|
||||
}
|
||||
}
|
||||
@@ -9890,7 +9905,10 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
|
||||
new_pos,
|
||||
"error while evaluating const constructor");
|
||||
} else {
|
||||
const Instance& const_instance = Instance::Cast(constructor_result);
|
||||
// Const constructors can return null in the case where a const native
|
||||
// factory returns a null value. Thus we cannot use a Instance::Cast here.
|
||||
Instance& const_instance = Instance::Handle();
|
||||
const_instance ^= constructor_result.raw();
|
||||
new_object = new LiteralNode(new_pos,
|
||||
Instance::ZoneHandle(const_instance.raw()));
|
||||
if (!type_bound.IsNull()) {
|
||||
|
||||
@@ -102,6 +102,11 @@ patch class int {
|
||||
int onError(String source) }) {
|
||||
return Primitives.parseInt(source, radix, onError);
|
||||
}
|
||||
|
||||
patch factory int.fromEnvironment(String name, {int defaultValue}) {
|
||||
throw new UnsupportedError(
|
||||
'int.fromEnvironement can only be used as a const constructor');
|
||||
}
|
||||
}
|
||||
|
||||
patch class double {
|
||||
@@ -219,6 +224,18 @@ patch class String {
|
||||
}
|
||||
return Primitives.stringFromCharCodes(charCodes);
|
||||
}
|
||||
|
||||
patch factory String.fromEnvironment(String name, {String defaultValue}) {
|
||||
throw new UnsupportedError(
|
||||
'String.fromEnvironement can only be used as a const constructor');
|
||||
}
|
||||
}
|
||||
|
||||
patch class bool {
|
||||
patch factory bool.fromEnvironment(String name, {bool defaultValue}) {
|
||||
throw new UnsupportedError(
|
||||
'bool.fromEnvironement can only be used as a const constructor');
|
||||
}
|
||||
}
|
||||
|
||||
patch class RegExp {
|
||||
|
||||
@@ -12,10 +12,11 @@ part of dart.core;
|
||||
* bool.
|
||||
*/
|
||||
class bool {
|
||||
factory bool._uninstantiable() {
|
||||
throw new UnsupportedError(
|
||||
"class bool cannot be instantiated");
|
||||
}
|
||||
/**
|
||||
* Returns the boolean for the given environment variable [name] or
|
||||
* [defaultValue] if [name] is not present.
|
||||
*/
|
||||
external const factory bool.fromEnvironment(String name, {bool defaultValue});
|
||||
|
||||
/**
|
||||
* Returns [:"true":] if the receiver is [:true:], or [:"false":] if the
|
||||
|
||||
@@ -252,4 +252,12 @@ abstract class int extends num {
|
||||
external static int parse(String source,
|
||||
{ int radix,
|
||||
int onError(String source) });
|
||||
|
||||
/**
|
||||
* Returns the integer value for the given environment variable
|
||||
* [name] or [defaultValue] if [name] is not present. If the value
|
||||
* of the environment variable is not a valid integer literal a
|
||||
* [FormatException] is thrown.
|
||||
*/
|
||||
external const factory int.fromEnvironment(String name, {int defaultValue});
|
||||
}
|
||||
|
||||
@@ -124,6 +124,13 @@ abstract class String implements Comparable<String>, Pattern {
|
||||
return new String.fromCharCodes(charCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string for the given environment variable [name] or
|
||||
* [defaultValue] if [name] is not present.
|
||||
*/
|
||||
external const factory String.fromEnvironment(String name,
|
||||
{String defaultValue});
|
||||
|
||||
/**
|
||||
* Gets the character (as a single-code-unit [String]) at the given [index].
|
||||
*
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
main() {
|
||||
const bool.fromEnvironment('NOT_FOUND', defaultValue: ''); /// 01: compile-time error
|
||||
const bool.fromEnvironment('NOT_FOUND', defaultValue: 1); /// 02: compile-time error
|
||||
const bool.fromEnvironment(null); /// 03: compile-time error
|
||||
const bool.fromEnvironment(1); /// 04: compile-time error
|
||||
const bool.fromEnvironment([]); /// 05: compile-time error
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isNull(const bool.fromEnvironment('NOT_FOUND'));
|
||||
Expect.isTrue(const bool.fromEnvironment('NOT_FOUND', defaultValue: true));
|
||||
Expect.isFalse(const bool.fromEnvironment('NOT_FOUND', defaultValue: false));
|
||||
Expect.isNull(const bool.fromEnvironment('NOT_FOUND', defaultValue: null));
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=true -Db=false
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isTrue(const bool.fromEnvironment('a'));
|
||||
Expect.isFalse(const bool.fromEnvironment('b'));
|
||||
}
|
||||
@@ -2,6 +2,33 @@
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
# Skip these tests until XXX.fromEnvironment in dart2js lands.
|
||||
[ $compiler == dart2js || $compiler == dart2dart]
|
||||
bool_from_environment2_test: Skip
|
||||
bool_from_environment_default_value_test: Skip
|
||||
bool_from_environment_test: Skip
|
||||
int_from_environment2_test: Skip
|
||||
int_from_environment3_test: Skip
|
||||
int_from_environment_default_value_test: Skip
|
||||
int_from_environment_test: Skip
|
||||
string_from_environment2_test: Skip
|
||||
string_from_environment3_test: Skip
|
||||
string_from_environment_default_value: Skip
|
||||
string_from_environment_test: Skip
|
||||
|
||||
[ $compiler == none && $runtime == drt ]
|
||||
bool_from_environment2_test: Skip
|
||||
bool_from_environment_default_value_test: Skip
|
||||
bool_from_environment_test: Skip
|
||||
int_from_environment2_test: Skip
|
||||
int_from_environment3_test: Skip
|
||||
int_from_environment_default_value_test: Skip
|
||||
int_from_environment_test: Skip
|
||||
string_from_environment2_test: Skip
|
||||
string_from_environment3_test: Skip
|
||||
string_from_environment_default_value: Skip
|
||||
string_from_environment_test: Skip
|
||||
|
||||
[ $compiler == none ]
|
||||
unicode_test: Fail # Bug 6706
|
||||
compare_to2_test: Fail # Bug 4018
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=x -Db=- -Dc=0xg
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isNull(const int.fromEnvironment('a'));
|
||||
Expect.isNull(const int.fromEnvironment('b'));
|
||||
Expect.isNull(const int.fromEnvironment('c'));
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
main() {
|
||||
const int.fromEnvironment('NOT_FOUND', defaultValue: ''); /// 01: compile-time error
|
||||
const int.fromEnvironment('NOT_FOUND', defaultValue: true); /// 02: compile-time error
|
||||
const int.fromEnvironment(null); /// 03: compile-time error
|
||||
const int.fromEnvironment(1); /// 04: compile-time error
|
||||
const int.fromEnvironment([]); /// 05: compile-time error
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isNull(const int.fromEnvironment('NOT_FOUND'));
|
||||
Expect.equals(12345, const int.fromEnvironment('NOT_FOUND', defaultValue: 12345));
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=1 -Db=-12 -Dc=0x123 -Dd=-0x1234
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.equals(1, const int.fromEnvironment('a'));
|
||||
Expect.equals(-12, const int.fromEnvironment('b'));
|
||||
Expect.equals(0x123, const int.fromEnvironment('c'));
|
||||
Expect.equals(-0x1234, const int.fromEnvironment('d'));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=a -Da=bb -Db=bb -Dc=ccc -Da=ccc -Db=ccc
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.equals('ccc', const String.fromEnvironment('a'));
|
||||
Expect.equals('ccc', const String.fromEnvironment('b'));
|
||||
Expect.equals('ccc', const String.fromEnvironment('c'));
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
main() {
|
||||
const String.fromEnvironment('NOT_FOUND', defaultValue: 1); /// 01: compile-time error
|
||||
const String.fromEnvironment('NOT_FOUND', defaultValue: true); /// 02: compile-time error
|
||||
const String.fromEnvironment(null); /// 03: compile-time error
|
||||
const String.fromEnvironment(1); /// 04: compile-time error
|
||||
const String.fromEnvironment([]); /// 05: compile-time error
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.isNull(const String.fromEnvironment('NOT_FOUND'));
|
||||
Expect.equals('x',
|
||||
const String.fromEnvironment('NOT_FOUND', defaultValue: 'x'));
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
// SharedOptions=-Da=a -Db=bb -Dc=ccc -Dd=
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
Expect.equals('a', const String.fromEnvironment('a'));
|
||||
Expect.equals('bb', const String.fromEnvironment('b'));
|
||||
Expect.equals('ccc', const String.fromEnvironment('c'));
|
||||
Expect.equals('', const String.fromEnvironment('d'));
|
||||
}
|
||||
Reference in New Issue
Block a user