From f5b653e66e681b3022b963d0f7d6ea936ff61f75 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 25 Feb 2014 17:40:50 -0500 Subject: [PATCH] De @mut the bindings. --- global.rs | 95 ++++++++++---------- js.rc | 4 +- name_pool.rs | 31 ------- rust.rs | 250 +++++++++++++++++++++------------------------------ 4 files changed, 149 insertions(+), 231 deletions(-) delete mode 100644 name_pool.rs diff --git a/global.rs b/global.rs index 3f3f7af4b..718a3b772 100644 --- a/global.rs +++ b/global.rs @@ -14,13 +14,13 @@ use glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, use std::libc::c_uint; use std::str::raw::from_c_str; use std::cast::transmute; -use name_pool::*; use std::ptr::null; use std::ptr; use jsapi; use jsapi::{JSClass, JSContext, JSVal, JSFunctionSpec, JSBool, JSNativeWrapper}; use jsapi::{JS_EncodeString, JS_free, JS_ValueToBoolean, JS_ValueToString}; use jsapi::{JS_ReportError, JS_ValueToSource, JS_GC, JS_GetRuntime}; +use jsfriendapi::JSJitInfo; use JSCLASS_IS_GLOBAL; use JSCLASS_HAS_RESERVED_SLOTS; use JSCLASS_GLOBAL_SLOT_COUNT; @@ -28,9 +28,9 @@ use JS_ARGV; use JSVAL_VOID; use JS_SET_RVAL; -pub fn basic_class(np: @mut NamePool, name: ~str) -> JSClass { +pub fn basic_class(name: &'static str) -> JSClass { JSClass { - name: np.add(name), + name: name.as_ptr() as *i8, flags: JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + 1), addProperty: unsafe { Some(transmute(GetJSClassHookStubPointer(PROPERTY_STUB))) }, delProperty: unsafe { Some(transmute(GetJSClassHookStubPointer(PROPERTY_STUB))) }, @@ -56,8 +56,8 @@ pub fn basic_class(np: @mut NamePool, name: ~str) -> JSClass { } } -pub fn global_class(np: @mut NamePool) -> JSClass { - basic_class(np, ~"global") +pub fn global_class() -> JSClass { + basic_class("global") } pub unsafe fn jsval_to_rust_str(cx: *JSContext, vp: *jsapi::JSString) -> ~str { @@ -124,48 +124,49 @@ pub extern fn assert(cx: *JSContext, argc: c_uint, vp: *mut JSVal) -> JSBool { } } -pub fn debug_fns(np: @mut NamePool) -> ~[JSFunctionSpec] { - ~[ - JSFunctionSpec { - name: np.add(~"debug"), - call: JSNativeWrapper { - op: Some(debug), - info: null() - }, - nargs: 0, - flags: 0, - selfHostedName: null() +static debug_name: [i8, ..6] = ['d' as i8, 'e' as i8, 'b' as i8, 'u' as i8, 'g' as i8, 0 as i8]; +static assert_name: [i8, ..7] = ['a' as i8, 's' as i8, 's' as i8, 'e' as i8, 'r' as i8, 't' as i8, 0 as i8]; +static gc_name: [i8, ..3] = ['g' as i8, 'c' as i8, 0 as i8]; + +pub static DEBUG_FNS: &'static [JSFunctionSpec] = &[ + JSFunctionSpec { + name: &debug_name as *i8, + call: JSNativeWrapper { + op: Some(debug), + info: 0 as *JSJitInfo }, - JSFunctionSpec { - name: np.add(~"assert"), - call: JSNativeWrapper { - op: Some(assert), - info: null() - }, - nargs: 1, - flags: 0, - selfHostedName: null() + nargs: 0, + flags: 0, + selfHostedName: 0 as *i8 + }, + JSFunctionSpec { + name: &assert_name as *i8, + call: JSNativeWrapper { + op: Some(assert), + info: 0 as *JSJitInfo }, - JSFunctionSpec { - name: np.add(~"gc"), - call: JSNativeWrapper { - op: Some(gc), - info: null() - }, - nargs: 1, - flags: 0, - selfHostedName: null() + nargs: 0, + flags: 0, + selfHostedName: 0 as *i8 + }, + JSFunctionSpec { + name: &gc_name as *i8, + call: JSNativeWrapper { + op: Some(gc), + info: 0 as *JSJitInfo }, - JSFunctionSpec { - name: null(), - call: JSNativeWrapper { - op: None, - info: null(), - }, - nargs: 0, - flags: 0, - selfHostedName: null() - } - ] -} - + nargs: 0, + flags: 0, + selfHostedName: 0 as *i8 + }, + JSFunctionSpec { + name: 0 as *i8, + call: JSNativeWrapper { + op: None, + info: 0 as *JSJitInfo, + }, + nargs: 0, + flags: 0, + selfHostedName: 0 as *i8 + } +]; diff --git a/js.rc b/js.rc index 272eee0dc..3d1c1b898 100644 --- a/js.rc +++ b/js.rc @@ -25,7 +25,6 @@ use jsapi::JS_ComputeThis; use std::libc::types::common::c99::uint32_t; pub use jsval::{JSVAL_TO_OBJECT, JSVAL_IS_PRIMITIVE, JSVAL_IS_OBJECT}; use rust::jsobj; -pub use name_pool::NamePool; // These are just macros in jsapi.h pub use JS_NewRuntime = jsapi::JS_Init; @@ -40,7 +39,6 @@ pub use jsfriendapi::JSJitInfo; pub mod jsapi; pub mod linkhack; -pub mod name_pool; pub mod rust; pub mod global; pub mod glue; @@ -147,7 +145,7 @@ pub fn result(n: JSBool) -> Result<(),()> { if n != ERR {Ok(())} else {Err(())} } pub fn result_obj(o: jsobj) -> Result { - if o.ptr != null() {Ok(o)} else {Err(())} + if o.borrow().ptr != null() {Ok(o)} else {Err(())} } #[inline(always)] diff --git a/name_pool.rs b/name_pool.rs deleted file mode 100644 index 742b9e7c0..000000000 --- a/name_pool.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use std::cast; -use std::libc::c_char; - -pub struct NamePool { - strbufs: ~[~[u8]] -} - -pub fn NamePool() -> @mut NamePool { - @mut NamePool { - strbufs: ~[] - } -} - -impl NamePool { - pub fn add(&mut self, s: ~str) -> *c_char { - unsafe { - let mut strbuf = ~[]; - for i in range(0, s.len()) { - strbuf.push(s[i]); - } - strbuf.push(0); - - self.strbufs.push(strbuf); - return cast::transmute(&self.strbufs[self.strbufs.len() - 1][0]); - } - } -} diff --git a/rust.rs b/rust.rs index c4c91f9c5..4a1e6bc1d 100644 --- a/rust.rs +++ b/rust.rs @@ -7,7 +7,7 @@ use std::libc::types::os::arch::c95::{size_t, c_uint}; use std::libc::{c_char, uintptr_t}; use std::num; -use std::hashmap::HashMap; +use std::rc; use jsapi::*; use default_stacksize; use default_heapsize; @@ -16,8 +16,6 @@ use JSOPTION_METHODJIT; use JSOPTION_TYPE_INFERENCE; use JSVAL_NULL; use ERR; -use name_pool::*; -use global::global_class; use std::ptr; use std::ptr::null; use result; @@ -29,7 +27,7 @@ use green::task::GreenTask; // ___________________________________________________________________________ // friendly Rustic API to runtimes -pub type rt = @rt_rsrc; +pub type rt = rc::Rc; pub struct rt_rsrc { ptr : *JSRuntime, @@ -44,15 +42,20 @@ impl Drop for rt_rsrc { } pub fn new_runtime(p: *JSRuntime) -> rt { - return @rt_rsrc { + return rc::Rc::new(rt_rsrc { ptr: p - } + }) +} + +pub trait RtUtils { + fn cx(&self) -> rc::Rc; } -impl rt_rsrc { - pub fn cx(@self) -> @Cx { +impl RtUtils for rc::Rc { + fn cx(&self) -> rc::Rc { unsafe { - new_context(JS_NewContext(self.ptr, default_stacksize as size_t), self) + new_context(JS_NewContext(self.borrow().ptr, + default_stacksize as size_t), self.clone()) } } } @@ -86,7 +89,6 @@ pub fn rt() -> rt { pub struct Cx { ptr: *JSContext, rt: rt, - classes: @mut HashMap<~str, @JSClass>, } #[unsafe_destructor] @@ -98,101 +100,95 @@ impl Drop for Cx { } } -pub fn new_context(ptr: *JSContext, rt: rt) -> @Cx { - return @Cx { +pub fn new_context(ptr: *JSContext, rt: rt) -> rc::Rc { + return rc::Rc::new(Cx { ptr: ptr, rt: rt, - classes: @mut HashMap::new() - } + }) } - -impl Cx { - pub fn rooted_obj(@self, obj: *JSObject) -> jsobj { - let jsobj = @jsobj_rsrc {cx: self, cxptr: self.ptr, ptr: obj}; + +pub trait CxUtils { + fn rooted_obj(&self, obj: *JSObject) -> jsobj; + fn new_compartment(&self, globcls: *JSClass) -> Result,()>; + fn new_compartment_with_global(&self, global: *JSObject) -> Result,()>; +} + +impl CxUtils for rc::Rc { + fn rooted_obj(&self, obj: *JSObject) -> jsobj { + let cxptr = self.borrow().ptr; + let jsobj = rc::Rc::new(jsobj_rsrc {cx: self.clone(), cxptr: cxptr, ptr: obj}); unsafe { - JS_AddObjectRoot(self.ptr, ptr::to_unsafe_ptr(&jsobj.ptr)); + JS_AddObjectRoot(cxptr, &jsobj.borrow().ptr); } jsobj } - pub fn set_default_options_and_version(@self) { + fn new_compartment(&self, globcls: *JSClass) -> Result,()> { + unsafe { + let ptr = self.borrow().ptr; + let globobj = JS_NewGlobalObject(ptr, globcls, null()); + result(JS_InitStandardClasses(ptr, globobj)).and_then(|_ok| { + let compartment = rc::Rc::new(Compartment { + cx: self.clone(), + global_obj: self.rooted_obj(globobj), + }); + self.borrow().set_cx_private(ptr::to_unsafe_ptr(compartment.borrow()) as *()); + Ok(compartment) + }) + } + } + + fn new_compartment_with_global(&self, global: *JSObject) -> Result,()> { + let compartment = rc::Rc::new(Compartment { + cx: self.clone(), + global_obj: self.rooted_obj(global), + }); + unsafe { + self.borrow().set_cx_private(ptr::to_unsafe_ptr(compartment.borrow()) as *()); + } + Ok(compartment) + } +} + +impl Cx { + pub fn set_default_options_and_version(&self) { self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT | JSOPTION_TYPE_INFERENCE); self.set_version(JSVERSION_LATEST); } - pub fn set_options(@self, v: c_uint) { + pub fn set_options(&self, v: c_uint) { unsafe { JS_SetOptions(self.ptr, v); } } - pub fn set_version(@self, v: i32) { + pub fn set_version(&self, v: i32) { unsafe { JS_SetVersion(self.ptr, v); } } - pub fn set_logging_error_reporter(@self) { + pub fn set_logging_error_reporter(&self) { unsafe { JS_SetErrorReporter(self.ptr, reportError); } } - pub fn set_error_reporter(@self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) { + pub fn set_error_reporter(&self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) { unsafe { JS_SetErrorReporter(self.ptr, reportfn); } } - pub fn new_compartment(@self, - globclsfn: |@mut NamePool| -> JSClass) - -> Result<@mut Compartment,()> { - unsafe { - let np = NamePool(); - let globcls = @globclsfn(np); - let globobj = JS_NewGlobalObject(self.ptr, ptr::to_unsafe_ptr(&*globcls), null()); - result(JS_InitStandardClasses(self.ptr, globobj)).and_then(|_ok| { - let compartment = @mut Compartment { - cx: self, - name_pool: np, - global_funcs: ~[], - global_props: ~[], - global_class: globcls, - global_obj: self.rooted_obj(globobj), - global_protos: @mut HashMap::new() - }; - self.set_cx_private(ptr::to_unsafe_ptr(&*compartment) as *()); - Ok(compartment) - }) - } - } - - pub fn new_compartment_with_global(@self, global: *JSObject) -> Result<@mut Compartment,()> { - let np = NamePool(); - let compartment = @mut Compartment { - cx: self, - name_pool: np, - global_funcs: ~[], - global_props: ~[], - global_class: @global_class(np), - global_obj: self.rooted_obj(global), - global_protos: @mut HashMap::new() - }; - unsafe { - self.set_cx_private(ptr::to_unsafe_ptr(&*compartment) as *()); - } - Ok(compartment) - } - - pub fn evaluate_script(@self, glob: jsobj, script: ~str, filename: ~str, line_num: uint) + pub fn evaluate_script(&self, glob: jsobj, script: ~str, filename: ~str, line_num: uint) -> Result<(),()> { let script_utf16 = script.to_utf16(); filename.to_c_str().with_ref(|filename_cstr| { let rval: JSVal = JSVAL_NULL; debug!("Evaluating script from {:s} with content {}", filename, script); unsafe { - if ERR == JS_EvaluateUCScript(self.ptr, glob.ptr, + if ERR == JS_EvaluateUCScript(self.ptr, glob.borrow().ptr, script_utf16.as_ptr(), script_utf16.len() as c_uint, filename_cstr, line_num as c_uint, ptr::to_unsafe_ptr(&rval)) { @@ -208,26 +204,19 @@ impl Cx { }) } - pub fn lookup_class_name(@self, s: ~str) -> @JSClass { - // FIXME: expect should really take a lambda... - let error_msg = format!("class {:s} not found in class table", s); - let name = self.classes.find(&s); - *(name.expect(error_msg)) - } - - pub unsafe fn get_cx_private(@self) -> *() { + pub unsafe fn get_cx_private(&self) -> *() { cast::transmute(JS_GetContextPrivate(self.ptr)) } - pub unsafe fn set_cx_private(@self, data: *()) { + pub unsafe fn set_cx_private(&self, data: *()) { JS_SetContextPrivate(self.ptr, cast::transmute(data)); } - pub unsafe fn get_obj_private(@self, obj: *JSObject) -> *() { + pub unsafe fn get_obj_private(&self, obj: *JSObject) -> *() { cast::transmute(JS_GetPrivate(obj)) } - pub unsafe fn set_obj_private(@self, obj: *JSObject, data: *()) { + pub unsafe fn set_obj_private(&self, obj: *JSObject, data: *()) { JS_SetPrivate(obj, cast::transmute(data)); } } @@ -246,98 +235,59 @@ pub extern fn reportError(_cx: *JSContext, msg: *c_char, report: *JSErrorReport) // compartment pub struct Compartment { - cx: @Cx, - name_pool: @mut NamePool, - global_funcs: ~[@~[JSFunctionSpec]], - global_props: ~[@~[JSPropertySpec]], - global_class: @JSClass, + cx: rc::Rc, global_obj: jsobj, - global_protos: @mut HashMap<~str, jsobj> } impl Compartment { - pub fn define_functions(@mut self, - specfn: |@mut NamePool| -> ~[JSFunctionSpec]) - -> Result<(),()> { - let specvec = @specfn(self.name_pool); - self.global_funcs.push(specvec); + pub fn define_functions(&self, specvec: &'static [JSFunctionSpec]) -> Result<(),()> { unsafe { - result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specvec.as_ptr())) + result(JS_DefineFunctions(self.cx.borrow().ptr, + self.global_obj.borrow().ptr, + specvec.as_ptr())) } } - pub fn define_properties(@mut self, specfn: || -> ~[JSPropertySpec]) -> Result<(),()> { - let specvec = @specfn(); - self.global_props.push(specvec); + pub fn define_properties(&self, specvec: &'static [JSPropertySpec]) -> Result<(),()> { unsafe { - result(JS_DefineProperties(self.cx.ptr, self.global_obj.ptr, specvec.as_ptr())) + result(JS_DefineProperties(self.cx.borrow().ptr, + self.global_obj.borrow().ptr, + specvec.as_ptr())) } } - pub fn define_property(@mut self, - name: ~str, - value: JSVal, - getter: JSPropertyOp, setter: JSStrictPropertyOp, - attrs: c_uint) - -> Result<(),()> { + pub fn define_property(&self, + name: &'static str, + value: JSVal, + getter: JSPropertyOp, setter: JSStrictPropertyOp, + attrs: c_uint) + -> Result<(),()> { unsafe { - result(JS_DefineProperty(self.cx.ptr, - self.global_obj.ptr, - self.add_name(name), - value, - Some(getter), - Some(setter), - attrs)) + name.to_c_str().with_ref(|name| { + result(JS_DefineProperty(self.cx.borrow().ptr, + self.global_obj.borrow().ptr, + name, + value, + Some(getter), + Some(setter), + attrs)) + }) } } - pub fn new_object(@mut self, class_name: ~str, proto: *JSObject, parent: *JSObject) + pub fn new_object(&self, classptr: *JSClass, proto: *JSObject, parent: *JSObject) -> Result { unsafe { - let classptr = self.cx.lookup_class_name(class_name); - let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, &*classptr, proto, parent)); + let obj = self.cx.rooted_obj(JS_NewObject(self.cx.borrow().ptr, classptr, proto, parent)); result_obj(obj) } } - pub fn new_object_with_proto(@mut self, class_name: ~str, proto_name: ~str, parent: *JSObject) - -> Result { - let classptr = self.cx.lookup_class_name(class_name); - let proto = self.global_protos.find(&proto_name.clone()).expect( - format!("new_object_with_proto: expected to find {:s} in the proto \ - table", proto_name)); - unsafe { - let obj = self.cx.rooted_obj(JS_NewObject(self.cx.ptr, ptr::to_unsafe_ptr(&*classptr), - proto.ptr, parent)); - result_obj(obj) - } - } - pub fn get_global_proto(@mut self, name: ~str) -> jsobj { - let proto = self.global_protos.get(&name); - *proto - } - pub fn stash_global_proto(@mut self, name: ~str, proto: jsobj) { - let global_protos = self.global_protos; - if !global_protos.insert(name, proto) { - fail!(~"Duplicate global prototype registered; you're gonna have a bad time.") - } - } - pub fn register_class(@mut self, class_fn: |x: @mut Compartment| -> JSClass) { - let classptr = @class_fn(self); - if !self.cx.classes.insert( - unsafe { from_c_str(classptr.name) }, - classptr) { - fail!(~"Duplicate JSClass registered; you're gonna have a bad time.") - } - } - pub fn add_name(@mut self, name: ~str) -> *c_char { - self.name_pool.add(name.clone()) - } } // ___________________________________________________________________________ // objects -pub type jsobj = @jsobj_rsrc; +pub type jsobj = rc::Rc; pub struct jsobj_rsrc { - cx: @Cx, + cx: rc::Rc, cxptr: *JSContext, ptr: *JSObject, } @@ -352,12 +302,12 @@ impl Drop for jsobj_rsrc { } impl jsobj_rsrc { - pub fn new_object(&self, cx: @Cx, cxptr: *JSContext, ptr: *JSObject) -> jsobj { - return @jsobj_rsrc { + pub fn new_object(&self, cx: rc::Rc, cxptr: *JSContext, ptr: *JSObject) -> jsobj { + return rc::Rc::new(jsobj_rsrc { cx: cx, cxptr: cxptr, ptr: ptr - } + }) } } @@ -365,14 +315,14 @@ impl jsobj_rsrc { // random utilities pub trait to_jsstr { - fn to_jsstr(self, cx: @Cx) -> *JSString; + fn to_jsstr(self, cx: rc::Rc) -> *JSString; } impl to_jsstr for ~str { - fn to_jsstr(self, cx: @Cx) -> *JSString { + fn to_jsstr(self, cx: rc::Rc) -> *JSString { unsafe { let cbuf = cast::transmute(self.as_ptr()); - JS_NewStringCopyN(cx.ptr, cbuf, self.len() as size_t) + JS_NewStringCopyN(cx.borrow().ptr, cbuf, self.len() as size_t) } } }