Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Display for Objects #171

Closed
Closed
Changes from 12 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0076f08
Added the initial re-implementation of Display for Objects
IovoslavIovchev Oct 19, 2019
8ce28e6
Added internal object slots printing
IovoslavIovchev Oct 19, 2019
72dca2f
Used INSTANCE_PROTOTYPE instead of "__proto__"
IovoslavIovchev Oct 19, 2019
f20fb6c
Updated TODO comment
IovoslavIovchev Oct 19, 2019
85024eb
rustfmt
IovoslavIovchev Oct 19, 2019
5788f6e
Fixed clippy and unit tests
IovoslavIovchev Oct 19, 2019
995ab5c
WIP: Added a working prototype for detecting cycles
IovoslavIovchev Oct 20, 2019
5ecadf1
Refactored the object printing logic
IovoslavIovchev Oct 20, 2019
fa73b84
Reverted test.js
IovoslavIovchev Oct 20, 2019
70f7d0a
Fixed print identation
IovoslavIovchev Oct 20, 2019
394cc64
rustfmt
IovoslavIovchev Oct 21, 2019
05a2748
Added printing for the internal_slots
IovoslavIovchev Oct 21, 2019
b9698e4
Fixed missing comma between internal slots & props when printing
IovoslavIovchev Oct 22, 2019
9c1b765
Merge branch 'master' into feature/object-printing
IovoslavIovchev Oct 22, 2019
3e0b399
Clippy
IovoslavIovchev Oct 22, 2019
0a076c1
Merge branch 'master' into feature/object-printing
IovoslavIovchev Nov 1, 2019
4c2814f
Merge remote-tracking branch 'upstream/master' into feature/object-pr…
IovoslavIovchev Nov 2, 2019
b26433c
Implemented a macro for printing objects & refactored
IovoslavIovchev Nov 3, 2019
390e265
Merge remote-tracking branch 'upstream/master' into feature/object-pr…
IovoslavIovchev Nov 9, 2019
1bf4ccd
Used display_obj in console.log
IovoslavIovchev Nov 9, 2019
80af637
rustfmt
IovoslavIovchev Nov 9, 2019
16a9610
Merge remote-tracking branch 'upstream/master' into feature/object-pr…
IovoslavIovchev Nov 12, 2019
4bb4624
Merge branch 'feature/object-printing' of github.com:IovoslavIovchev/…
IovoslavIovchev Nov 12, 2019
d13e1ad
Fixed String & Array prototypes length not being set
IovoslavIovchev Nov 16, 2019
fda92c7
Extracted common logic in a function
IovoslavIovchev Nov 16, 2019
877522e
Commented out problematic lines in `concat`
IovoslavIovchev Nov 16, 2019
bca21e1
rustfmt
IovoslavIovchev Nov 16, 2019
9f7be25
Refactored console.rs & value.rs
IovoslavIovchev Nov 16, 2019
0a2196b
Fixed log_string_from looking for wrong string slot
IovoslavIovchev Nov 16, 2019
f999365
Reverted commented test
IovoslavIovchev Nov 16, 2019
c77057c
Removed Array & String prototype lengths' getters
IovoslavIovchev Nov 17, 2019
6ce305c
Removed unused functions
IovoslavIovchev Nov 17, 2019
870e727
rustfmt
IovoslavIovchev Nov 17, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 95 additions & 2 deletions src/lib/js/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use gc_derive::{Finalize, Trace};
use serde_json::{map::Map, Number as JSONNumber, Value as JSONValue};
use std::{
any::Any,
collections::HashSet,
f64::NAN,
fmt::{self, Display},
ops::{Add, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, Mul, Not, Rem, Shl, Shr, Sub},
Expand Down Expand Up @@ -572,7 +573,7 @@ impl Default for ValueData {

impl Display for ValueData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
match self {
ValueData::Null => write!(f, "null"),
ValueData::Undefined => write!(f, "undefined"),
ValueData::Boolean(v) => write!(f, "{}", v),
Expand All @@ -587,7 +588,99 @@ impl Display for ValueData {
_ => v.to_string(),
}
),
ValueData::Object(_) => write!(f, "{{}}"),
v @ ValueData::Object(_) => {
// A simple helper for getting the address of a value
// TODO: Find a more general place for this, as it can be used in other situations as well
fn address_of<T>(t: &T) -> usize {
let my_ptr: *const T = t;
my_ptr as usize
}

// We keep track of which objects we have encountered by keeping their
// in-memory address in this set
let mut encounters = HashSet::new();

fn display_obj(
data: &ValueData,
encounters: &mut HashSet<usize>,
indent: usize,
) -> String {
match *data {
ValueData::Object(ref v) => {
// The in-memory address of the current object
let addr = address_of(v.borrow().deref());

// We need not continue if this object has already been
// printed up the current chain
if encounters.contains(&addr) {
return String::from("'[Cycle]'");
}

// Mark the current object as encountered
encounters.insert(addr);

// Each time we print a nested object we need to increment the
// indentation size in order to pretty print
let indentation = String::from_utf8(vec![b' '; indent])
.expect("Could not create indentation string");

let properties = v
.borrow()
.properties
.iter()
.map(|(key, val)| {
let v = &val
.value
.as_ref()
.expect("Could not get the property's value");

format!(
"{}{}: {}",
indentation,
key,
display_obj(v, encounters, indent.wrapping_add(4))
)
})
.collect::<Vec<String>>()
.join(",\n");

let internal_slots = v
.borrow()
.internal_slots
.iter()
.map(|(key, val)| {
format!(
"{}{}: {}",
indentation,
key,
display_obj(&val, encounters, indent.wrapping_add(4))
)
})
.collect::<Vec<String>>()
.join(",\n");

// If the current object is referenced in a different branch,
// it will not cause an infinte printing loop, so it is safe to be printed again
encounters.remove(&addr);

let closing_indent =
String::from_utf8(vec![b' '; indent.wrapping_sub(4)]).expect(
"Could not create the closing brace's indentation string",
);

format!(
"{{\n{}\n{}\n{}}}",
properties, internal_slots, closing_indent
)
}

// Every other type of data is printed as is
_ => format!("{}", data),
}
}

write!(f, "{}", display_obj(&v, &mut encounters, 4))
}
ValueData::Integer(v) => write!(f, "{}", v),
ValueData::Function(ref v) => match *v.borrow() {
Function::NativeFunc(_) => write!(f, "function() {{ [native code] }}"),
Expand Down