github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/v8/lib/storage_object.cc (about) 1 // Copyright (C) 2017 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see 17 // <http://www.gnu.org/licenses/>. 18 // 19 20 #include "storage_object.h" 21 #include "../engine.h" 22 #include "instruction_counter.h" 23 #include "logger.h" 24 #include <math.h> 25 26 static StorageGetFunc GET = NULL; 27 static StoragePutFunc PUT = NULL; 28 static StorageDelFunc DEL = NULL; 29 30 void NewStorageType(Isolate *isolate, Local<ObjectTemplate> globalTpl) { 31 Local<FunctionTemplate> type = 32 FunctionTemplate::New(isolate, StorageConstructor); 33 Local<String> className = String::NewFromUtf8(isolate, "NativeStorage"); 34 type->SetClassName(className); 35 36 Local<ObjectTemplate> instanceTpl = type->InstanceTemplate(); 37 instanceTpl->SetInternalFieldCount(1); 38 instanceTpl->Set( 39 String::NewFromUtf8(isolate, "get"), 40 FunctionTemplate::New(isolate, StorageGetCallback), 41 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 42 PropertyAttribute::ReadOnly)); 43 instanceTpl->Set( 44 String::NewFromUtf8(isolate, "set"), 45 FunctionTemplate::New(isolate, StoragePutCallback), 46 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 47 PropertyAttribute::ReadOnly)); 48 instanceTpl->Set( 49 String::NewFromUtf8(isolate, "put"), 50 FunctionTemplate::New(isolate, StoragePutCallback), 51 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 52 PropertyAttribute::ReadOnly)); 53 instanceTpl->Set( 54 String::NewFromUtf8(isolate, "del"), 55 FunctionTemplate::New(isolate, StorageDelCallback), 56 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 57 PropertyAttribute::ReadOnly)); 58 59 globalTpl->Set(className, type, 60 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 61 PropertyAttribute::ReadOnly)); 62 } 63 64 void NewStorageTypeInstance(Isolate *isolate, Local<Context> context, 65 void *lcsHandler, void *gcsHandler) { 66 Local<ObjectTemplate> storageHandlerTpl = ObjectTemplate::New(isolate); 67 Local<Object> handlers = 68 storageHandlerTpl->NewInstance(context).ToLocalChecked(); 69 70 handlers->DefineOwnProperty( 71 context, String::NewFromUtf8(isolate, "lcs"), 72 External::New(isolate, lcsHandler), 73 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 74 PropertyAttribute::ReadOnly)); 75 handlers->DefineOwnProperty( 76 context, String::NewFromUtf8(isolate, "gcs"), 77 External::New(isolate, gcsHandler), 78 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 79 PropertyAttribute::ReadOnly)); 80 81 context->Global()->DefineOwnProperty( 82 context, String::NewFromUtf8(isolate, "_native_storage_handlers"), 83 handlers, 84 static_cast<PropertyAttribute>(PropertyAttribute::DontDelete | 85 PropertyAttribute::ReadOnly)); 86 } 87 88 void InitializeStorage(StorageGetFunc get, StoragePutFunc put, 89 StorageDelFunc del) { 90 GET = get; 91 PUT = put; 92 DEL = del; 93 } 94 95 void StorageConstructor(const FunctionCallbackInfo<Value> &info) { 96 Isolate *isolate = info.GetIsolate(); 97 Local<Object> thisArg = info.Holder(); 98 99 if (info.Length() != 1) { 100 isolate->ThrowException(String::NewFromUtf8( 101 isolate, "Storage constructor requires only 1 argument")); 102 return; 103 } 104 105 Local<Value> handler = info[0]; 106 if (!handler->IsExternal()) { 107 isolate->ThrowException(String::NewFromUtf8( 108 isolate, 109 "Storage constructor requires a member of _native_storage_handlers")); 110 return; 111 } 112 113 thisArg->SetInternalField(0, handler); 114 } 115 116 void StorageGetCallback(const FunctionCallbackInfo<Value> &info) { 117 Isolate *isolate = info.GetIsolate(); 118 Local<Object> thisArg = info.Holder(); 119 Local<External> handler = Local<External>::Cast(thisArg->GetInternalField(0)); 120 121 if (info.Length() != 1) { 122 isolate->ThrowException( 123 String::NewFromUtf8(isolate, "Storage.get() requires only 1 argument")); 124 return; 125 } 126 127 Local<Value> key = info[0]; 128 if (!key->IsString()) { 129 isolate->ThrowException(String::NewFromUtf8(isolate, "key must be string")); 130 return; 131 } 132 133 size_t cnt = 0; 134 char *value = 135 GET(handler->Value(), *String::Utf8Value(key->ToString()), &cnt); 136 if (value == NULL) { 137 info.GetReturnValue().SetNull(); 138 } else { 139 info.GetReturnValue().Set(String::NewFromUtf8(isolate, value)); 140 free(value); 141 } 142 143 // record storage usage. 144 IncrCounter(isolate, isolate->GetCurrentContext(), cnt); 145 } 146 147 void StoragePutCallback(const FunctionCallbackInfo<Value> &info) { 148 Isolate *isolate = info.GetIsolate(); 149 Local<Object> thisArg = info.Holder(); 150 Local<External> handler = Local<External>::Cast(thisArg->GetInternalField(0)); 151 152 if (info.Length() != 2) { 153 isolate->ThrowException( 154 String::NewFromUtf8(isolate, "Storage.put() requires only 2 argument")); 155 return; 156 } 157 158 Local<Value> key = info[0]; 159 if (!key->IsString()) { 160 isolate->ThrowException(String::NewFromUtf8(isolate, "key must be string")); 161 return; 162 } 163 164 Local<Value> value = info[1]; 165 if (!value->IsString()) { 166 isolate->ThrowException( 167 String::NewFromUtf8(isolate, "value must be string")); 168 return; 169 } 170 171 Local<String> key_str = key->ToString(); 172 Local<String> val_str = value->ToString(); 173 174 size_t cnt = 0; 175 int ret = PUT(handler->Value(), *String::Utf8Value(key_str), 176 *String::Utf8Value(val_str), &cnt); 177 info.GetReturnValue().Set(ret); 178 179 // record storage usage. 180 IncrCounter(isolate, isolate->GetCurrentContext(), cnt); 181 } 182 183 void StorageDelCallback(const FunctionCallbackInfo<Value> &info) { 184 Isolate *isolate = info.GetIsolate(); 185 Local<Object> thisArg = info.Holder(); 186 Local<External> handler = Local<External>::Cast(thisArg->GetInternalField(0)); 187 188 if (info.Length() != 1) { 189 isolate->ThrowException( 190 String::NewFromUtf8(isolate, "Storage.del() requires only 1 argument")); 191 return; 192 } 193 194 Local<Value> key = info[0]; 195 if (!key->IsString()) { 196 isolate->ThrowException(String::NewFromUtf8(isolate, "key must be string")); 197 return; 198 } 199 200 size_t cnt = 0; 201 int ret = DEL(handler->Value(), *String::Utf8Value(key->ToString()), &cnt); 202 info.GetReturnValue().Set(ret); 203 204 // record storage usage. 205 IncrCounter(isolate, isolate->GetCurrentContext(), cnt); 206 }