node-native-printer icon indicating copy to clipboard operation
node-native-printer copied to clipboard

Unable to build on Node v12

Open Alan-Liang opened this issue 6 years ago • 1 comments

v8 seems to have removed v8::Value::ToString(). Consider replacing str->ToString() with isolate, str->ToString(isolate->GetCurrentContext()).FromMaybe(v8::Local<v8::String>()).

Alan-Liang avatar Oct 27 '19 07:10 Alan-Liang

I tried to fix it by the following code:

API.cpp

#include "API.hpp"

using namespace methods;

namespace API{
	CALLBACK(listPrinters){
		
		ISOLATE; 
		
		cups_dest_t* dests;
		int numDests = cupsGetDests(&dests);

		Local<Array> printers = Array::New(isolate, numDests);

		for(int i = 0; i < numDests; i++){
			Local<Object> printer = Object::New(isolate);
			printer->Set(isolate->GetCurrentContext(), UTF8_STRING("name"), UTF8_STRING(dests[i].name));
			printer->Set(isolate->GetCurrentContext(), UTF8_STRING("default"), Boolean::New(isolate, static_cast<bool>(dests[i].is_default)));
			
			printers->Set(isolate->GetCurrentContext(), i, printer);
		}

		cupsFreeDests(numDests, dests);
		args.GetReturnValue().Set(printers);
	}

	CALLBACK(printerInfo){

		ISOLATE;

		if(args.Length() < 1){
			THROW_EXCEPTION("Too few arguments");
			return;
		}

		String::Utf8Value printer(S_STR(args[0]));

		cups_dest_t* dest = getPrinter(*printer);

		if(dest == NULL){
			THROW_EXCEPTION("Printer not found or error retrieving printer");
			return;
		}

		cups_job_t* printerJobs;
		int num_jobs = cupsGetJobs(&printerJobs, dest->name, 0, CUPS_WHICHJOBS_ALL);

		Local<Object> result = Object::New(isolate);
		Local<Object> jobs = Array::New(isolate);
		Local<Object> CUPSOptions = Object::New(isolate);

		for(int i = 0; i < dest->num_options; i++){
			CUPSOptions->Set(isolate->GetCurrentContext(), UTF8_STRING(dest->options[i].name), UTF8_STRING(dest->options[i].value));
		}

		char id[5], priority[5], size[5];

		for(int i = 0; i < num_jobs; i++){
			Local<Object> job = Object::New(isolate);
			
			sprintf(id, "%d", printerJobs[i].id);
			sprintf(priority, "%d", printerJobs[i].priority);
			sprintf(size, "%d", printerJobs[i].size);

			job->Set(isolate->GetCurrentContext(), UTF8_STRING("completed_time"), UTF8_STRING(httpGetDateString(printerJobs[i].completed_time)));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("creation_time"), UTF8_STRING(httpGetDateString(printerJobs[i].creation_time)));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("format"), UTF8_STRING(printerJobs[i].format));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("id"), UTF8_STRING(id));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("priority"), UTF8_STRING(priority));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("processing_time"), UTF8_STRING(httpGetDateString(printerJobs[i].processing_time)));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("size"), UTF8_STRING(size));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("status"), UTF8_STRING(getJobStatusString(printerJobs[i].state)));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("title"), UTF8_STRING(printerJobs[i].title));
			job->Set(isolate->GetCurrentContext(), UTF8_STRING("user"), UTF8_STRING(printerJobs[i].user));

			jobs->Set(isolate->GetCurrentContext(), i, job);
		}

		cupsFreeJobs(num_jobs, printerJobs);
		free(dest);
		// result->Set(UTF8_STRING("infos"), infos);
		result->Set(isolate->GetCurrentContext(), UTF8_STRING("jobs"), jobs);
		result->Set(isolate->GetCurrentContext(), UTF8_STRING("CUPSOptions"), CUPSOptions);

		args.GetReturnValue().Set(result);
	}

	CALLBACK(printerOptions){
		ISOLATE;

		if(args.Length() < 1){
			THROW_EXCEPTION("Too few arguments");
			return;
		}
		
		String::Utf8Value printer(S_STR(args[0]));

		cups_dest_t* dest = getPrinter(*printer);

		if(dest == NULL){
			THROW_EXCEPTION("Printer not found");
			return;
		}
	
		const char* filename = cupsGetPPD(dest->name);
		ppd_file_t* ppd = ppdOpenFile(filename);
		
		ppdMarkDefaults(ppd);
		cupsMarkOptions(ppd, dest->num_options, dest->options);

		Local<Object> result = Object::New(isolate);
		Local<Object> resOptions = Object::New(isolate);
		Local<Object> resDefaults = Object::New(isolate);

		ppd_group_t* group = ppd->groups;

		for (int i = 0; i < ppd->num_groups; i++)
        {
			ppd_option_t* option = group->options;
			for (int j = 0; j < group->num_options; j++)
			{
				Local<Array> choices = Array::New(isolate, option->num_choices);
				resOptions->Set(isolate->GetCurrentContext(), UTF8_STRING(option->keyword), choices);
				ppd_choice_t* choice = option->choices;
				
				for(int h = 0; h < option->num_choices; h++){
					choices->Set(isolate->GetCurrentContext(), h, UTF8_STRING(choice->text));
					
					if(choice->marked)
						resDefaults->Set(isolate->GetCurrentContext(), UTF8_STRING(option->keyword), UTF8_STRING(choice->text));

					choice++;
				}

				option++;
			}

			group++;
		}

		ppdClose(ppd);
		free(dest);
		
		result->Set(isolate->GetCurrentContext(), UTF8_STRING("options"), resOptions);
		result->Set(isolate->GetCurrentContext(), UTF8_STRING("defaultOptions"), resDefaults);
		args.GetReturnValue().Set(result);
	}

	CALLBACK(defaultPrinterName){
		
		ISOLATE;
		
		cups_dest_t* printer = getPrinter(NULL);
		args.GetReturnValue().Set(UTF8_STRING(strdup(printer->name)));
		free(printer);
	}

	CALLBACK(print){
		using namespace std;

		ISOLATE;
		if(args.Length() < 3){
			THROW_EXCEPTION("Too few arguments");
			return;
		}

		string printer(*(String::Utf8Value(S_STR(args[0]))));
		string file(*(String::Utf8Value(S_STR(args[1]))));
		string options(*(String::Utf8Value(S_STR(args[2]))));
		
		cups_dest_t* dest = getPrinter(printer.c_str());
		printer = string(dest->name);

		string cmd = "lp -d " + printer + " " + file + " " + options;

		string result = exec(cmd.c_str());
		
		args.GetReturnValue().Set(UTF8_STRING(result.c_str()));
		free(dest);
	}
}

API.hpp

#include <node.h>

#include "methods.hpp"

using namespace v8;

#define CALLBACK(name) 			void name(const FunctionCallbackInfo<Value>& args)
#define ISOLATE 				v8::Isolate* isolate = v8::Isolate::GetCurrent()
#define THROW_EXCEPTION(msg) 	isolate->ThrowException(v8::Exception::TypeError(String::NewFromUtf8(isolate, msg).FromMaybe(v8::Local<v8::String>())))
#define UTF8_STRING(str) 		String::NewFromUtf8(isolate, str).FromMaybe(v8::Local<v8::String>())
#define S_STR(str) isolate, str->ToString(isolate->GetCurrentContext()).FromMaybe(v8::Local<v8::String>())

// Same as before

Alan-Liang avatar Oct 27 '19 08:10 Alan-Liang