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  }